home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
x11
/
networke
/
cow
/
cowl-1.000
/
cowl-1
/
socket.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-05-04
|
99KB
|
3,627 lines
/*
* Socket.c
*
* Kevin P. Smith 1/29/89 UDP stuff v1.0 by Andy McFadden Feb-Apr 1992
*
* UDP protocol v1.0
*
* Routines to allow connection to the xtrek server.
*/
#include "copyright2.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <math.h>
#include <errno.h>
#include "Wlib.h"
#include "defs.h"
#include "struct.h"
#include "data.h"
#include "packets.h"
#ifdef SHORT_PACKETS
#include "sp.h"
#endif
/* #define INCLUDE_SCAN /* include Amdahl scanning beams */
/* #define INCLUDE_VISTRACT /* include visible tractor beams */
#ifdef GATEWAY
/*
* (these values are now defined in "main.c":) char *gw_mach =
* "charon"; |client gateway; strcmp(serverName) int gw_serv_port =
* 5000; |what to tell the server to use int gw_port = 5001;
* |where we will contact gw int gw_local_port = 5100; |where we
* expect gw to contact us
*
* The client binds to "5100" and sends "5000" to the server (TCP). The server
* sees that and sends a UDP packet to gw on port udp5000, which passes it
* through to port udp5100 on the client. The client-gw gets the server's
* host and port from recvfrom. (The client can't use the same method since
* these sockets are one-way only, so it connect()s to gw_port (udp5001) on
* the gateway machine regardless of what the server sends.)
*
* So all we need in .gwrc is: udp 5000 5001 tde.uts 5100
*
* assuming the client is on tde.uts. Note that a UDP declaration will work for
* ANY server, but you need one per player, and the client has to have the
* port numbers in advance.
*
* If we're using a standard server, we're set. If we're running through a
* gatewayed server, we have to do some unpleasant work on the server side...
*/
#endif
int handleMessage(), handlePhaser(), handlePlyrInfo();
int handlePlayer(), handleSelf(), handleStatus();
int handleWarning(), handleTorp(), handleTorpInfo();
int handlePlanet(), handleQueue(), handlePickok(), handleLogin();
int handlePlasmaInfo(), handlePlasma();
int handleKills(), handleFlags(), handlePStatus();
int handleMotd(), handleMask();
int handleBadVersion(), handlePlanetLoc();
int handleHostile(), handleStats(), handlePlyrLogin();
int handleReserved();
#ifdef RSA
int handleRSAKey();
#endif
int handleScan();
int handleUdpReply(), handleSequence();
#ifdef FEATURE
extern int handleFeature ();
extern void reportFeatures ();
#endif
#ifdef NEED_EXIT
#ifdef sgi
void exit(int status);
#else /* sgi */
int exit();
#endif /* sgi */
#endif
extern char *strcpy_return();
#ifdef PING
int handlePing(); /* ping.c */
#endif
#ifdef SHORT_PACKETS
int handleShortReply(), handleVPlayer(), handleVTorp(), handleSelfShort(),
handleSelfShip(), handleVPlanet(), handleSWarning();
int handleVTorpInfo(), handleSMessage();
static char numofbits[256] =
{0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1,
2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1,
2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2,
3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1,
2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2,
3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2,
3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3,
4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1,
2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2,
3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2,
3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3,
4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2,
3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3,
4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3,
4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4,
5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8};
static int vtsize[9] =
{4, 8, 8, 12, 12, 16, 20, 20, 24}; /* How big is the torppacket */
static int vtdata[9] =
{0, 3, 5, 7, 9, 12, 14, 16, 18};/* How big is Torpdata */
static int vtisize[9] =
{4, 7, 9, 11, 13, 16, 18, 20, 22}; /* 4 byte Header + torpdata */
int spwinside = 500;/* WINSIDE from Server */
#define SPWINSIDE 500 /* To make it safe */
LONG spgwidth = GWIDTH; /* GWITHT from Server */
static
int my_x, my_y; /* for rotation we need to keep track of our
real coordinates */
#endif /* SHORT_PACKETS */
#ifdef PACKET_LOG
int Log_Packet();
int ALL_BYTES = 0; /* To log all bytes */
#endif
struct packet_handler handlers[] =
{
{0, NULL}, /* record 0 */
{sizeof(struct mesg_spacket), handleMessage}, /* SP_MESSAGE */
{sizeof(struct plyr_info_spacket), handlePlyrInfo}, /* SP_PLAYER_INFO */
{sizeof(struct kills_spacket), handleKills}, /* SP_KILLS */
{sizeof(struct player_spacket), handlePlayer}, /* SP_PLAYER */
{sizeof(struct torp_info_spacket), handleTorpInfo}, /* SP_TORP_INFO */
{sizeof(struct torp_spacket), handleTorp}, /* SP_TORP */
{sizeof(struct phaser_spacket), handlePhaser}, /* SP_PHASER */
{sizeof(struct plasma_info_spacket), handlePlasmaInfo}, /* SP_PLASMA_INFO */
{sizeof(struct plasma_spacket), handlePlasma}, /* SP_PLASMA */
{sizeof(struct warning_spacket), handleWarning}, /* SP_WARNING */
{sizeof(struct motd_spacket), handleMotd}, /* SP_MOTD */
{sizeof(struct you_spacket), handleSelf}, /* SP_YOU */
{sizeof(struct queue_spacket), handleQueue}, /* SP_QUEUE */
{sizeof(struct status_spacket), handleStatus}, /* SP_STATUS */
{sizeof(struct planet_spacket), handlePlanet}, /* SP_PLANET */
{sizeof(struct pickok_spacket), handlePickok}, /* SP_PICKOK */
{sizeof(struct login_spacket), handleLogin}, /* SP_LOGIN */
{sizeof(struct flags_spacket), handleFlags}, /* SP_FLAGS */
{sizeof(struct mask_spacket), handleMask}, /* SP_MASK */
{sizeof(struct pstatus_spacket), handlePStatus}, /* SP_PSTATUS */
{sizeof(struct badversion_spacket), handleBadVersion}, /* SP_BADVERSION */
{sizeof(struct hostile_spacket), handleHostile}, /* SP_HOSTILE */
{sizeof(struct stats_spacket), handleStats}, /* SP_STATS */
{sizeof(struct plyr_login_spacket), handlePlyrLogin}, /* SP_PL_LOGIN */
{sizeof(struct reserved_spacket), handleReserved}, /* SP_RESERVED */
{sizeof(struct planet_loc_spacket), handlePlanetLoc}, /* SP_PLANET_LOC */
#ifdef HANDLE_SCAN
{sizeof(struct scan_spacket), handleScan}, /* SP_SCAN (ATM) */
#else
{0, NULL}, /* won't be called */
#endif
{sizeof(struct udp_reply_spacket), handleUdpReply}, /* SP_UDP_STAT */
{sizeof(struct sequence_spacket), handleSequence}, /* SP_SEQUENCE */
{sizeof(struct sc_sequence_spacket), handleSequence}, /* SP_SC_SEQUENCE */
#ifdef RSA
{sizeof(struct rsa_key_spacket), handleRSAKey}, /* SP_RSA_KEY */
#else
{0, NULL}, /* #31, and exit won't really be called */
#endif
{0, NULL}, /* 32 */
{0, NULL}, /* 33 */
{0, NULL}, /* 34 */
{0, NULL}, /* 35 */
{0, NULL}, /* 36 */
{0, NULL}, /* 37 */
{0, NULL}, /* 38 */
{0, NULL}, /* 39 */
#ifdef SHORT_PACKETS
{sizeof(struct shortreply_spacket), handleShortReply}, /* SP_S_REPLY */
{-1, handleSMessage}, /* SP_S_MESSAGE */
{-1 /* sizeof(struct warning_s_spacket) */ , handleSWarning}, /* SP_S_WARNING */
{sizeof(struct youshort_spacket), handleSelfShort}, /* SP_S_YOU */
{sizeof(struct youss_spacket), handleSelfShip}, /* SP_S_YOU_SS */
{-1, /* variable */ handleVPlayer}, /* SP_S_PLAYER */
#else
{0, NULL}, /* 40 */
{0, NULL}, /* 41 */
{0, NULL}, /* 42 */
{0, NULL}, /* 43 */
{0, NULL}, /* 44 */
{0, NULL}, /* 45 */
#endif
#ifdef PING
{sizeof(struct ping_spacket), handlePing}, /* SP_PING; 46 */
#else
{0, NULL}, /* 46 */
#endif
#ifdef SHORT_PACKETS
{-1, /* variable */ handleVTorp}, /* SP_S_TORP; 47 */
{-1, handleVTorpInfo}, /* SP_S_TORP_INFO; 48 */
{20, handleVTorp}, /* SP_S_8_TORP; 49 */
{-1, handleVPlanet}, /* SP_S_PLANET; 50 */
#else
{0, NULL}, /* 47 */
{0, NULL}, /* 48 */
{0, NULL}, /* 49 */
{0, NULL}, /* 50 */
#endif
#ifdef FEATURE
{0, NULL}, /* 51 */
{0, NULL}, /* 52 */
{0, NULL}, /* 53 */
{0, NULL}, /* 54 */
{0, NULL}, /* 55 */
{0, NULL}, /* 56 */
{0, NULL}, /* 57 */
{0, NULL}, /* 58 */
{0, NULL}, /* 59 */
{sizeof(struct feature_cpacket), handleFeature}, /* CP_FEATURE; 60 */
#endif
};
int sizes[] =
{
0, /* record 0 */
sizeof(struct mesg_cpacket), /* CP_MESSAGE */
sizeof(struct speed_cpacket),/* CP_SPEED */
sizeof(struct dir_cpacket), /* CP_DIRECTION */
sizeof(struct phaser_cpacket), /* CP_PHASER */
sizeof(struct plasma_cpacket), /* CP_PLASMA */
sizeof(struct torp_cpacket), /* CP_TORP */
sizeof(struct quit_cpacket), /* CP_QUIT */
sizeof(struct login_cpacket),/* CP_LOGIN */
sizeof(struct outfit_cpacket), /* CP_OUTFIT */
sizeof(struct war_cpacket), /* CP_WAR */
sizeof(struct practr_cpacket), /* CP_PRACTR */
sizeof(struct shield_cpacket), /* CP_SHIELD */
sizeof(struct repair_cpacket), /* CP_REPAIR */
sizeof(struct orbit_cpacket),/* CP_ORBIT */
sizeof(struct planlock_cpacket), /* CP_PLANLOCK */
sizeof(struct playlock_cpacket), /* CP_PLAYLOCK */
sizeof(struct bomb_cpacket), /* CP_BOMB */
sizeof(struct beam_cpacket), /* CP_BEAM */
sizeof(struct cloak_cpacket),/* CP_CLOAK */
sizeof(struct det_torps_cpacket), /* CP_DET_TORPS */
sizeof(struct det_mytorp_cpacket), /* CP_DET_MYTORP */
sizeof(struct copilot_cpacket), /* CP_COPILOT */
sizeof(struct refit_cpacket),/* CP_REFIT */
sizeof(struct tractor_cpacket), /* CP_TRACTOR */
sizeof(struct repress_cpacket), /* CP_REPRESS */
sizeof(struct coup_cpacket), /* CP_COUP */
sizeof(struct socket_cpacket), /* CP_SOCKET */
sizeof(struct options_cpacket), /* CP_OPTIONS */
sizeof(struct bye_cpacket), /* CP_BYE */
sizeof(struct dockperm_cpacket), /* CP_DOCKPERM */
sizeof(struct updates_cpacket), /* CP_UPDATES */
sizeof(struct resetstats_cpacket), /* CP_RESETSTATS */
sizeof(struct reserved_cpacket), /* CP_RESERVED */
#ifdef INCLUDE_SCAN
sizeof(struct scan_cpacket), /* CP_SCAN (ATM) */
#else
0,
#endif
sizeof(struct udp_req_cpacket), /* CP_UDP_REQ */
sizeof(struct sequence_cpacket), /* CP_SEQUENCE */
#ifdef RSA
sizeof(struct rsa_key_cpacket), /* CP_RSA_KEY */
#else
0, /* 37 */
#endif
0, /* 38 */
0, /* 39 */
0, /* 40 */
0, /* 41 */
#ifdef PING
sizeof(struct ping_cpacket), /* CP_PING_RESPONSE; 42 */
#else
0, /* 42 */
#endif
#ifdef SHORT_PACKETS
sizeof(struct shortreq_cpacket), /* CP_S_REQ; 43 */
sizeof(struct threshold_cpacket), /* CP_S_THRS; 44 */
-1, /* CP_S_MESSAGE; 45 */
#else
0, /* 43 */
0, /* 44 */
0, /* 45 */
#endif
#ifdef FEATURE
0, /* 46 */
0, /* 47 */
0, /* 48 */
0, /* 49 */
0, /* 50 */
0, /* 51 */
0, /* 52 */
0, /* 53 */
0, /* 54 */
0, /* 55 */
0, /* 56 */
0, /* 57 */
0, /* 58 */
0, /* 59 */
sizeof (struct feature_cpacket), /* CP_FEATURE; 60 */
#endif
};
#define NUM_PACKETS (sizeof(handlers) / sizeof(handlers[0]) - 1)
#define NUM_SIZES (sizeof(sizes) / sizeof(sizes[0]) - 1)
#ifdef PACKET_LOG
/*
* stuff useful for logging server packets to see how much bandwidth * netrek
* is really using
*/
int log_packets = 0;/* whether or not to be logging packets */
int packet_log[NUM_PACKETS]; /* number of packets logged */
int outpacket_log[NUM_SIZES];
#endif /* PACKET_LOG */
int serverDead = 0;
#define BUFSIZE 3072
char buf[BUFSIZE];
static int udpLocalPort = 0;
static int udpServerPort = 0;
static LONG serveraddr = 0;
static LONG sequence = 0;
static int drop_flag = 0;
static int chan = -1; /* tells sequence checker where packet is
* from */
static short fSpeed, fDirection, fShield, fOrbit, fRepair, fBeamup,
fBeamdown, fCloak, fBomb, fDockperm, fPhaser, fPlasma,
fPlayLock, fPlanLock, fTractor, fRepress;
/* reset all the "force command" variables */
resetForce()
{
fSpeed = fDirection = fShield = fOrbit = fRepair = fBeamup = fBeamdown =
fCloak = fBomb = fDockperm = fPhaser = fPlasma = fPlayLock = fPlanLock =
fTractor = fRepress = -1;
}
/*
* If something we want to happen hasn't yet, send it again.
*
* The low byte is the request, the high byte is a max count. When the max
* count reaches zero, the client stops trying. Checking is done with a
* macro for speed & clarity.
*/
#define FCHECK_FLAGS(flag, force, const) { \
if (force > 0) { \
if (((me->p_flags & flag) && 1) ^ ((force & 0xff) && 1)) { \
speedReq.type = const; \
speedReq.speed = (force & 0xff); \
sendServerPacket(&speedReq); \
V_UDPDIAG(("Forced %d:%d\n", const, force & 0xff)); \
force -= 0x100; \
if (force < 0x100) force = -1; /* give up */ \
} else \
force = -1; \
} \
}
#define FCHECK_VAL(value, force, const) { \
if (force > 0) { \
if ((value) != (force & 0xff)) { \
speedReq.type = const; \
speedReq.speed = (force & 0xff); \
sendServerPacket(&speedReq); \
V_UDPDIAG(("Forced %d:%d\n", const, force & 0xff)); \
force -= 0x100; \
if (force < 0x100) force = -1; /* give up */ \
} else \
force = -1; \
} \
}
#define FCHECK_TRACT(flag, force, const) { \
if (force > 0) { \
if (((me->p_flags & flag) && 1) ^ ((force & 0xff) && 1)) { \
tractorReq.type = const; \
tractorReq.state = ((force & 0xff) >= 0x40); \
tractorReq.pnum = (force & 0xff) & (~0x40); \
sendServerPacket(&tractorReq); \
V_UDPDIAG(("Forced %d:%d/%d\n", const, \
tractorReq.state, tractorReq.pnum)); \
force -= 0x100; \
if (force < 0x100) force = -1; /* give up */ \
} else \
force = -1; \
} \
}
checkForce()
{
struct speed_cpacket speedReq;
struct tractor_cpacket tractorReq;
FCHECK_VAL(me->p_speed, fSpeed, CP_SPEED); /* almost always repeats */
#ifdef nodef /* not needed */
FCHECK_VAL(me->p_dir, fDirection, CP_DIRECTION); /* (ditto) */
#endif
FCHECK_FLAGS(PFSHIELD, fShield, CP_SHIELD);
FCHECK_FLAGS(PFORBIT, fOrbit, CP_ORBIT);
FCHECK_FLAGS(PFREPAIR, fRepair, CP_REPAIR);
FCHECK_FLAGS(PFBEAMUP, fBeamup, CP_BEAM);
FCHECK_FLAGS(PFBEAMDOWN, fBeamdown, CP_BEAM);
FCHECK_FLAGS(PFCLOAK, fCloak, CP_CLOAK);
FCHECK_FLAGS(PFBOMB, fBomb, CP_BOMB);
FCHECK_FLAGS(PFDOCKOK, fDockperm, CP_DOCKPERM);
FCHECK_VAL(phasers[me->p_no].ph_status, fPhaser, CP_PHASER); /* bug: dir 0 */
FCHECK_VAL(plasmatorps[me->p_no].pt_status, fPlasma, CP_PLASMA); /* (ditto) */
FCHECK_FLAGS(PFPLOCK, fPlayLock, CP_PLAYLOCK);
FCHECK_FLAGS(PFPLLOCK, fPlanLock, CP_PLANLOCK);
FCHECK_TRACT(PFTRACT, fTractor, CP_TRACTOR);
FCHECK_TRACT(PFPRESS, fRepress, CP_REPRESS);
}
connectToServer(port)
int port;
{
int s;
struct sockaddr_in addr;
struct sockaddr_in naddr;
int len;
fd_set readfds;
struct timeval timeout;
struct hostent *hp;
int optval;
serverDead = 0;
if (sock != -1) {
shutdown(sock, 2);
close(sock);
sock = -1;
}
#ifdef nodef
sleep(3); /* I think this is necessary for some unknown
* reason */
#endif
printf("Waiting for connection (port %d). \n", port);
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("I can't create a socket\n");
exit(2);
}
/* allow local address resuse */
optval = 1;
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(int))
< 0) {
perror("setsockopt");
}
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(port);
if (bind(s, &addr, sizeof(addr)) < 0) {
#ifdef nodef
sleep(10);
if (bind(s, &addr, sizeof(addr)) < 0) {
sleep(10);
if (bind(s, &addr, sizeof(addr)) < 0) {
printf("I can't bind to port!\n");
exit(3);
}
}
#endif
perror("bind"); /* NEW */
exit(1);
}
if(listen(s, 1) < 0)
perror("listen");
len = sizeof(naddr);
tryagain:
timeout.tv_sec = 240; /* four minutes */
timeout.tv_usec = 0;
FD_ZERO(&readfds);
FD_SET(s, &readfds);
if(s >= max_fd)
max_fd = s+1;
if (select(max_fd, &readfds, NULL, NULL, &timeout) == 0) {
printf("Well, I think the server died!\n");
exit(0);
}
sock = accept(s, &naddr, &len);
if (sock == -1) {
goto tryagain;
}
if(sock >= max_fd)
max_fd = sock+1;
printf("Got connection.\n");
close(s);
pickSocket(port); /* new socket != port */
/*
* This is necessary; it tries to determine who the caller is,
* and set "serverName" and "serveraddr" appropriately.
*/
len = sizeof(struct sockaddr_in);
if (getpeername(sock, (struct sockaddr *) & addr, &len) < 0) {
perror("unable to get peername");
serverName = "nowhere";
} else {
serveraddr = addr.sin_addr.s_addr;
hp = gethostbyaddr((char *) &addr.sin_addr.s_addr, sizeof(LONG), AF_INET);
if (hp != NULL) {
serverName = (char *) malloc(strlen(hp->h_name) + 1);
strcpy(serverName, hp->h_name);
} else {
serverName = (char *) malloc(strlen(inet_ntoa(addr.sin_addr)) + 1);
strcpy(serverName, inet_ntoa(addr.sin_addr));
}
}
printf("Connection from server %s (0x%x)\n", serverName, serveraddr);
}
#ifdef nodef
set_tcp_opts(s)
int s;
{
int optval = 1;
struct protoent *ent;
ent = getprotobyname("TCP");
if (!ent) {
fprintf(stderr, "TCP protocol not found.\n");
return;
}
if (setsockopt(s, ent->p_proto, TCP_NODELAY, &optval, sizeof(int)) < 0)
perror("setsockopt");
}
set_udp_opts(s)
int s;
{
int optval = BUFSIZ;
struct protoent *ent;
ent = getprotobyname("UDP");
if (!ent) {
fprintf(stderr, "UDP protocol not found.\n");
return;
}
if (setsockopt(s, ent->p_proto, SO_RCVBUF, &optval, sizeof(int)) < 0)
perror("setsockopt");
}
#endif
callServer(port, server)
int port;
char *server;
{
int s;
struct sockaddr_in addr;
struct hostent *hp;
serverDead = 0;
printf("Calling %s on port %d.\n", server, port);
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("I can't create a socket\n");
exit(0);
}
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if ((addr.sin_addr.s_addr = inet_addr(server)) == -1) {
if ((hp = gethostbyname(server)) == NULL) {
printf("Who is %s?\n", server);
exit(0);
} else {
addr.sin_addr.s_addr = *(LONG *) hp->h_addr;
}
}
serveraddr = addr.sin_addr.s_addr;
if (connect(s, &addr, sizeof(addr)) < 0) {
printf("Server not listening!\n");
exit(0);
}
printf("Got connection.\n");
sock = s;
if(sock >= max_fd)
max_fd = sock+1;
#ifdef TREKHOPD
/*
* We use a different scheme from gw: we tell the server who we want to
* connect to and what our local UDP port is; it picks its own UDP ports
* and tells us what they are. This is MUCH more flexible and avoids a
* number of problems, and may come in handy if the blessed scheme
* changes. It's also slightly more work.
*/
{
extern int port_req, use_trekhopd, serv_port;
extern char *host_req;
struct mesg_cpacket msg;
struct mesg_spacket reply;
int n, count, *ip;
char *buf;
if (use_trekhopd) {
msg.type = SP_MESSAGE;
msg.group = msg.indiv = msg.pad1 = 0;
ip = (int *) msg.mesg;
*(ip++) = htons(port_req);
*(ip++) = htons(gw_local_port);
strncpy(msg.mesg + 8, login, 8);
strcpy(msg.mesg + 16, host_req);
if (gwrite(s, &msg, sizeof(struct mesg_cpacket)) < 0) {
fprintf(stderr, "trekhopd init failure\n");
exit(1);
}
printf("--- trekhopd request sent, awaiting reply\n");
/* now block waiting for reply */
count = sizeof(struct mesg_spacket);
for (buf = (char *) &reply; count; buf += n, count -= n) {
if ((n = read(s, buf, count)) <= 0) {
perror("trekhopd read");
exit(1);
}
}
if (reply.type != SP_MESSAGE) {
fprintf(stderr, "Got bogus reply from trekhopd (%d)\n",
reply.type);
exit(1);
}
ip = (int *) reply.mesg;
gw_serv_port = ntohl(*ip++);
gw_port = ntohl(*ip++);
serv_port = ntohl(*ip++);
printf ("--- trekhopd reply received\n");
/* printf("ports = %d/%d, %d\n", gw_serv_port, gw_port, serv_port); */
}
}
#endif /* TREKHOPD */
pickSocket(port); /* new socket != port */
}
isServerDead()
{
return (serverDead);
}
socketPause()
{
struct timeval timeout;
fd_set readfds;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
FD_ZERO(&readfds);
FD_SET(sock, &readfds);
if (udpSock >= 0) /* new */
FD_SET(udpSock, &readfds);
select(max_fd, &readfds, 0, 0, &timeout);
}
readFromServer(readfds)
fd_set *readfds;
{
int retval = 0;
if (serverDead)
return (0);
if(!readfds){
struct timeval timeout;
int rs;
fd_set mask;
readfds = &mask;
tryagain:
FD_ZERO(readfds);
FD_SET(sock, readfds);
if (udpSock >= 0)
FD_SET(udpSock, readfds);
timeout.tv_sec = 0;
timeout.tv_usec = 0;
if ((rs = select(max_fd, readfds, 0, 0, &timeout)) == 0){
dotimers();
return 0;
}
}
if (udpSock >= 0 && FD_ISSET(udpSock, readfds)) {
/* WAS V_ */
UDPDIAG(("Activity on UDP socket\n"));
chan = udpSock;
if (commStatus == STAT_VERIFY_UDP) {
warning("UDP connection established");
sequence = 0; /* reset sequence #s */
resetForce();
if (udpDebug)
printUdpInfo();
UDPDIAG(("UDP connection established.\n"));
commMode = COMM_UDP;
commStatus = STAT_CONNECTED;
commSwitchTimeout = 0;
if (udpClientRecv != MODE_SIMPLE)
sendUdpReq(COMM_MODE + udpClientRecv);
if (udpWin) {
udprefresh(UDP_CURRENT);
udprefresh(UDP_STATUS);
}
}
retval += doRead(udpSock);
}
/* Read info from the xtrek server */
if (FD_ISSET(sock, readfds)) {
chan = sock;
if (commMode == COMM_TCP)
drop_flag = 0; /* just in case */
retval += doRead(sock);
}
dotimers();
return (retval != 0); /* convert to 1/0 */
}
dotimers()
{
/* if switching comm mode, decrement timeout counter */
if (commSwitchTimeout > 0) {
if (!(--commSwitchTimeout)) {
/*
* timed out; could be initial request to non-UDP server (which
* won't be answered), or the verify packet got lost en route to the
* server. Could also be a request for TCP which timed out (weird),
* in which case we just reset anyway.
*/
commModeReq = commMode = COMM_TCP;
commStatus = STAT_CONNECTED;
if (udpSock >= 0)
closeUdpConn();
if (udpWin) {
udprefresh(UDP_CURRENT);
udprefresh(UDP_STATUS);
}
warning("Timed out waiting for UDP response from server");
UDPDIAG(("Timed out waiting for UDP response from server\n"));
}
}
/* if we're in a UDP "force" mode, check to see if we need to do something */
if (udpClientSend > 1 && commMode == COMM_UDP)
checkForce();
}
doRead(asock)
int asock;
{
struct timeval timeout;
fd_set readfds;
char *bufptr;
int size;
int count;
int temp;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
count = read(asock, buf, BUFSIZE - /* space for packet frag */BUFSIZE/4);
#ifdef NETSTAT
if (netstat &&
(asock == udpSock ||
commMode != COMM_UDP ||
udpClientRecv == MODE_TCP)){
ns_record_update(count);
}
#endif
if (debug)
printf("read %d bytes from %s socket\n",
count, asock == udpSock ? "UDP" : "TCP");
if (count <= 0) {
if (asock == udpSock) {
if (errno == ECONNREFUSED) {
struct sockaddr_in addr;
UDPDIAG(("asock=%d, sock=%d, udpSock=%d, errno=%d\n",
asock, sock, udpSock, errno));
UDPDIAG(("count=%d\n", count));
UDPDIAG(("Hiccup(%d)! Reconnecting\n", errno));
addr.sin_addr.s_addr = serveraddr;
addr.sin_port = htons(udpServerPort);
addr.sin_family = AF_INET;
if (connect(udpSock, &addr, sizeof(addr)) < 0) {
perror("connect");
UDPDIAG(("Unable to reconnect\n"));
/* and fall through to disconnect */
} else {
UDPDIAG(("Reconnect successful\n"));
return (0);
}
}
UDPDIAG(("*** UDP disconnected (res=%d, err=%d)\n",
count, errno));
warning("UDP link severed");
printUdpInfo();
closeUdpConn();
commMode = commModeReq = COMM_TCP;
commStatus = STAT_CONNECTED;
if (udpWin) {
udprefresh(UDP_STATUS);
udprefresh(UDP_CURRENT);
}
return (0);
}
printf("1) Got read() of %d. Server dead\n", count);
perror("1) read()");
serverDead = 1;
return (0);
}
bufptr = buf;
while (bufptr < buf + count) {
if (*bufptr < 1 || *bufptr > NUM_PACKETS || handlers[*bufptr].size == 0) {
int i;
fprintf(stderr, "Unknown packet type: %d\n", *bufptr);
#ifndef CORRUPTED_PACKETS
printf("count: %d, bufptr at %d, Content:\n", count,
bufptr - buf);
for (i = 0; i < count; i++) {
printf("0x%x, ", (unsigned int) buf[i]);
}
#endif
return (0);
}
size = handlers[*bufptr].size;
#ifdef SHORT_PACKETS
if (size == -1) { /* variable packet */
switch (*bufptr) {
case SP_S_MESSAGE:
size = ((unsigned char) bufptr[4]); /* IMPORTANT Changed */
break;
case SP_S_WARNING:
if ((unsigned char) bufptr[1] == STEXTE_STRING ||
(unsigned char) bufptr[1] == SHORT_WARNING) {
size = ((unsigned char) bufptr[3]);
} else
size = 4; /* Normal Packet */
break;
case SP_S_PLAYER:
if ((unsigned char) bufptr[1] & (unsigned char) 128) { /* Small +extended
* Header */
size = ((unsigned char) (bufptr[1] & 0x3f) * 4) + 4;
} else if ((unsigned char) bufptr[1] & 64) { /* Small Header */
size = ((unsigned char) (bufptr[1] & 0x3f) * 4) + 4;
} else { /* Big Header */
size = ((unsigned char) bufptr[1] * 4 + 12);
}
break;
case SP_S_TORP:
size = vtsize[numofbits[(unsigned char) bufptr[1]]];
break;
case SP_S_TORP_INFO:
size = (vtisize[numofbits[(unsigned char) bufptr[1]]] + numofbits[(unsigned char) bufptr[3]]);
break;
case SP_S_PLANET:
size = ((unsigned char) bufptr[1] * VPLANET_SIZE) + 2;
break;
default:
fprintf(stderr, "Unknown variable packet\n");
/*
exit(1);
*/
return 0;
break;
}
if ((size % 4) != 0){
size += (4 - (size % 4));
}
if(size <= 0){
fprintf(stderr, "Bad short-packet size value (%d)\n", size);
return 0;
}
if (debug)
printf("read variable packet size %d, type %d\n",
size, *bufptr);
}
#endif /* SHORT_PACKETS */
while (size > count + (buf - bufptr)) {
/*
* We wait for up to ten seconds for rest of packet. If we don't get
* it, we assume the server died.
*/
tryagain1:
timeout.tv_sec = 20;
timeout.tv_usec = 0;
FD_ZERO(&readfds);
FD_SET(asock, &readfds);
/* readfds=1<<asock; */
if ((temp=select(max_fd, &readfds, 0, 0, &timeout)) == 0) {
printf("Packet fragment. Server must be dead\n");
serverDead = 1;
return (0);
}
temp = read(asock, buf + count, size - (count + (buf - bufptr)));
count += temp;
if (temp <= 0) {
printf("2) Got read() of %d. Server is dead\n", temp);
serverDead = 1;
return (0);
}
}
if (handlers[*bufptr].handler != NULL) {
if (asock != udpSock ||
(!drop_flag || *bufptr == SP_SEQUENCE || *bufptr == SP_SC_SEQUENCE)) {
if (debug)
printf("read packet %d\n", *bufptr);
#ifdef RECORD
if (recordGame && recordFile != NULL && RECORDPACKET(*bufptr))
if ((fwrite(bufptr, size, 1, recordFile) != 1) ||
(putc(*bufptr, recordFile) == EOF)) {
perror("write: (recordFile)");
fclose(recordFile);
recordFile = NULL;
}
#endif
#ifdef PACKET_LOG
if (log_packets)
(void) Log_Packet((char) (*bufptr), size);
#endif
#ifdef PING
if (asock == udpSock)
packets_received++;
#endif
(*(handlers[*bufptr].handler)) (bufptr
#ifdef CORRUPTED_PACKETS
,asock
#endif
);
} else{
if(debug){
if(drop_flag) printf("%d bytes dropped.\n", size);
}
UDPDIAG(("Ignored type %d\n", *bufptr));
}
} else {
printf("Handler for packet %d not installed...\n", *bufptr);
}
bufptr += size;
#ifdef nodef
if (bufptr > buf + BUFSIZ) {
bcopy(buf + BUFSIZ, buf, BUFSIZ);
if (count == BUFSIZ * 2) {
tryagain2:
FD_ZERO(&readfds);
FD_SET(asock, &readfds);
/* readfds = 1<<asock; */
if ((temp=select(max_fd, &readfds, 0, 0, &timeout)) > 0) {
temp = read(asock, buf + BUFSIZ, BUFSIZ);
count = BUFSIZ + temp;
if (temp <= 0) {
printf("3) Got read() of %d. Server is dead\n", temp);
serverDead = 1;
return (0);
}
} else {
count = BUFSIZ;
}
} else {
count -= BUFSIZ;
}
bufptr -= BUFSIZ;
}
#endif
}
return (1);
}
handleTorp(packet)
struct torp_spacket *packet;
{
struct torp *thetorp;
#ifdef CORRUPTED_PACKETS
if (ntohs(packet->tnum) < 0 || ntohs(packet->tnum) >= MAXPLAYER * MAXTORP) {
fprintf(stderr, "handleTorp: bad index %d\n", ntohs(packet->tnum));
return;
}
#endif
thetorp = &torps[ntohs(packet->tnum)];
thetorp->t_x = ntohl(packet->x);
thetorp->t_y = ntohl(packet->y);
thetorp->t_dir = packet->dir;
#ifdef ROTATERACE
if (rotate) {
rotate_coord(&thetorp->t_x, &thetorp->t_y, rotate_deg,
GWIDTH / 2, GWIDTH / 2);
rotate_dir(&thetorp->t_dir, rotate_deg);
}
#endif
#ifdef BD
if (bd)
bd_test_torp(ntohs(packet->tnum), thetorp);
#endif
}
#ifdef SHORT_PACKETS
handleVTorp(sbuf)
unsigned char *sbuf;
{
unsigned char *which, *data;
unsigned char bitset;
struct torp *thetorp;
int dx, dy;
int shiftvar;
int i;
register int shift = 0; /* How many torps are extracted (for shifting
* ) */
/* now we must find the data ... :-) */
if (sbuf[0] == SP_S_8_TORP) {/* MAX packet */
bitset = 0xff;
which = &sbuf[1];
data = &sbuf[2];
} else { /* Normal Packet */
bitset = sbuf[1];
which = &sbuf[2];
data = &sbuf[3];
}
#ifdef CORRUPTED_PACKETS
/* we probably should do something clever here - jmn */
if(*which * 8 >= MAXPLAYER * MAXTORP){
fprintf(stderr, "handleVTorp: bad index %d\n", *which * 8);
return;
}
#endif
thetorp = &torps[((unsigned char) *which * 8)];
for (shift = 0, i = 0; /* (unsigned char)bitset != 0 */ i < 8;
i++,
thetorp++,
bitset >>= 1) {
if (bitset & 01) {
dx = (*data >> shift);
data++;
shiftvar = (unsigned char) *data; /* to silence gcc */
shiftvar <<= (8 - shift);
dx |= (shiftvar & 511);
shift++;
dy = (*data >> shift);
data++;
shiftvar = (unsigned char) *data; /* to silence gcc */
shiftvar <<= (8 - shift);
dy |= (shiftvar & 511);
shift++;
if (shift == 8) {
shift = 0;
data++;
}
/* This is necessary because TFREE/TMOVE is now encoded in the bitset */
if (thetorp->t_status == TFREE) {
thetorp->t_status = TMOVE; /* guess */
players[thetorp->t_owner].p_ntorp++;
}
/* NEW */
else if (thetorp->t_owner == me->p_no && thetorp->t_status == TEXPLODE)
thetorp->t_status = TMOVE;
/* Check if torp is visible */
if (dx > SPWINSIDE || dy > SPWINSIDE) {
thetorp->t_x = -100000; /* Not visible */
thetorp->t_y = -100000;
} else { /* visible */
thetorp->t_x = my_x + ((dx - SPWINSIDE / 2) * SCALE);
thetorp->t_y = my_y + ((dy - SPWINSIDE / 2) * SCALE);
#ifdef ROTATERACE
if (rotate) {
rotate_coord(&thetorp->t_x, &thetorp->t_y, rotate_deg,
GWIDTH / 2, GWIDTH / 2);
}
#endif
}
}
/* if */
else { /* We got a TFREE */
/* tsh */
if (thetorp->t_status &&
(thetorp->t_status != TEXPLODE)){
players[thetorp->t_owner].p_ntorp--;
thetorp->t_status = TFREE; /* That's no guess */
}
}
} /* for */
}
#endif
handleTorpInfo(packet)
struct torp_info_spacket *packet;
{
struct torp *thetorp;
#ifdef CORRUPTED_PACKETS
if (ntohs(packet->tnum) < 0 || ntohs(packet->tnum) >= MAXPLAYER * MAXTORP) {
fprintf(stderr, "handleTorpInfo: bad index %d\n", ntohs(packet->tnum));
return;
}
#endif
thetorp = &torps[ntohs(packet->tnum)];
if (packet->status == TEXPLODE && thetorp->t_status == TFREE) {
/* FAT: redundant explosion; don't update p_ntorp */
/*
* printf("texplode ignored\n");
*/
return;
}
if (thetorp->t_status == TFREE && packet->status) {
players[thetorp->t_owner].p_ntorp++;
#ifdef nodef
if (players[thetorp->t_owner].p_status == PEXPLODE)
fprintf(stderr, "TORP STARTED WHEN PLAYER EXPLODED\n");
#endif
/* BORG TEST */
#ifdef BD
if (bd)
bd_new_torp(ntohs(packet->tnum), thetorp);
#endif
}
if (thetorp->t_status && packet->status == TFREE) {
players[thetorp->t_owner].p_ntorp--;
}
thetorp->t_war = packet->war;
if (packet->status != thetorp->t_status) {
/* FAT: prevent explosion reset */
thetorp->t_status = packet->status;
if (thetorp->t_status == TEXPLODE) {
thetorp->t_fuse = NUMDETFRAMES;
}
}
}
handleStatus(packet)
struct status_spacket *packet;
{
status->tourn = packet->tourn;
status->armsbomb = ntohl(packet->armsbomb);
status->planets = ntohl(packet->planets);
status->kills = ntohl(packet->kills);
status->losses = ntohl(packet->losses);
status->time = ntohl(packet->time);
status->timeprod = ntohl(packet->timeprod);
if (debug) {
printf("SERVER STATS:\n");
printf("time: %d\n", status->time / (60 * 60 * 10));
printf("kills: %d\n", status->kills);
printf("losses: %d\n", status->losses);
printf("planets: %d\n", status->planets);
printf("armsbomb: %d\n", status->armsbomb);
}
}
handleSelf(packet)
struct you_spacket *packet;
{
#ifdef CORRUPTED_PACKETS
if (packet->pnum < 0 || packet->pnum >= MAXPLAYER) {
fprintf(stderr, "handleSelf: bad index %d\n", packet->pnum);
return;
}
#endif
me = &players[packet->pnum];
myship = &(me->p_ship);
mystats = &(me->p_stats);
me->p_hostile = packet->hostile;
me->p_swar = packet->swar;
me->p_armies = packet->armies;
#ifdef nodef
if (((me->p_flags & PFGREEN) && (ntohl(packet->flags) & PFRED)) ||
((me->p_flags & PFRED) && (ntohl(packet->flags) & PFGREEN)))
printf("green/red transition\n");
#endif
me->p_flags = ntohl(packet->flags);
if (me->p_flags & PFPLOCK) {
redrawPlayer[me->p_playerl] = 1;
}
me->p_damage = ntohl(packet->damage);
me->p_shield = ntohl(packet->shield);
me->p_fuel = ntohl(packet->fuel);
me->p_etemp = ntohs(packet->etemp);
me->p_wtemp = ntohs(packet->wtemp);
me->p_whydead = ntohs(packet->whydead);
me->p_whodead = ntohs(packet->whodead);
#ifdef INCLUDE_VISTRACT
if (packet->tractor & 0x40)
me->p_tractor = (short) packet->tractor & (~0x40); /* ATM - visible
* tractors */
#ifdef nodef /* tmp */
else
me->p_tractor = -1;
#endif /* nodef */
#endif
}
#ifdef SHORT_PACKETS
handleSelfShort(packet)
struct youshort_spacket *packet;
{
me = &players[packet->pnum];
myship = &(me->p_ship);
mystats = &(me->p_stats);
me->p_hostile = packet->hostile;
me->p_swar = packet->swar;
me->p_armies = packet->armies;
me->p_flags = ntohl(packet->flags);
me->p_whydead = packet->whydead;
me->p_whodead = packet->whodead;
}
handleSelfShip(packet)
struct youss_spacket *packet;
{
int x,y;
if (!me)
return; /* wait.. */
me->p_damage = ntohs(packet->damage);
me->p_shield = ntohs(packet->shield);
me->p_fuel = ntohs(packet->fuel);
me->p_etemp = ntohs(packet->etemp);
me->p_wtemp = ntohs(packet->wtemp);
/* Heiko told me to undefine this, it's supposed to update ship flags
more often? SRS 3/15/94 */
me->p_flags = (me->p_flags & 0xffffff00)|(unsigned char) packet->flags8;
}
#endif
handlePlayer(packet)
struct player_spacket *packet;
{
register struct player *pl;
int x,y;
#ifdef CORRUPTED_PACKETS
if (packet->pnum < 0 || packet->pnum >= MAXPLAYER) {
fprintf(stderr, "handlePlayer: bad index %d\n", packet->pnum);
return;
}
#endif
pl = &players[packet->pnum];
pl->p_dir = packet->dir;
x = htonl(packet->x);
y = htonl(packet->y);
pl->p_speed = packet->speed;
#ifdef WARP_DEAD
if (dead_warp && pl->p_speed == 14 && x==-10000 && y==-10000) {
pl->p_status = PEXPLODE;
x = pl->p_x;
y = pl->p_y;
if (pl->p_dir > DEADPACKETS)
pl->p_explode = EX_FRAMES;
else
pl->p_explode = 0;
redrawPlayer[packet->pnum] = updatePlayer[packet->pnum] = 1;
}
#endif
#ifdef CLOAK_MAXWARP
if (cloak_maxwarp && pl != me)
{
if(pl->p_speed == 15)
pl->p_flags |= PFCLOAK;
else
pl->p_flags &= ~(PFCLOAK);
}
#endif
pl->p_x = x;
pl->p_y = y;
redrawPlayer[packet->pnum] = 1;
#ifdef ROTATERACE
if (rotate) {
rotate_coord(&pl->p_x, &pl->p_y, rotate_deg, GWIDTH / 2, GWIDTH / 2);
rotate_dir(&pl->p_dir, rotate_deg);
}
#endif
}
#ifdef SHORT_PACKETS
handleVPlayer(sbuf)
unsigned char *sbuf;
{
register int speed, x, y, i, numofplayers, pl_no, save, galactic;
unsigned char *savebuf = sbuf;
register struct player *pl;
numofplayers = (unsigned char) sbuf[1] & 0x3f;
#ifdef CORRUPTED_PACKETS
/*
* should do something clever here - jmn if(pl_no < 0 || pl_no >=
* MAXPLAYER){ return; }
*/
#endif
#if MAXPLAYER > 32
if (sbuf[1] & (unsigned char) 128) { /* Short Header + Extended */
sbuf += 4;
for (i = 0; i < numofplayers; i++) {
pl_no = ((unsigned char) *sbuf & 0x1f) + 32;
if (pl_no >= MAXPLAYER)
continue; /* a little error check */
save = (unsigned char) *sbuf;
sbuf++;
pl = &players[pl_no];
pl->p_speed = (unsigned char) *sbuf & 15; /* SPEED */
#ifdef CLOAK_MAXWARP
if (cloak_maxwarp && pl != me) {
if(pl->p_speed == 15)
pl->p_flags |= PFCLOAK;
else
pl->p_flags &= ~(PFCLOAK);
}
#endif
pl->p_dir = (unsigned char) (*sbuf>>4) * 16; /* realDIR */
sbuf++;
x = (unsigned char) *sbuf++;
y = (unsigned char) *sbuf++; /* The lower 8 Bits are saved */
/* Now we must preprocess the coordinates */
if ((unsigned char) save & 64)
x |= 256;
if ((unsigned char) save & 128)
y |= 256;
#ifdef WARP_DEAD
if (dead_warp && pl->speed == 14 && x==-10000 && y==-10000) {
pl->p_status = PEXPLODE;
x = pl->p_x;
y = pl->p_y;
if (pl->p_dir > DEADPACKETS)
pl->p_explode = EX_FRAMES;
else
pl->p_explode = 0;
redrawPlayer[pl_no] = updatePlayer[pl_no] = 1;
}
#endif
/* Now test if it's galactic or local coord */
if (save & 32) { /* It's galactic */
redrawPlayer[pl_no] = 1;
if(x == 501 || y == 501){
x = -500;
y = -500;
}
pl->p_x = x * (GWIDTH / SPWINSIDE);
pl->p_y = y * (GWIDTH / SPWINSIDE);
#ifdef ROTATERACE
if (rotate) {
rotate_coord(&pl->p_x, &pl->p_y,
rotate_deg, GWIDTH / 2, GWIDTH / 2);
rotate_dir(&pl->p_dir, rotate_deg);
}
#endif
} else { /* Local */
redrawPlayer[pl->p_no] = 1;
pl->p_x = my_x + ((x - SPWINSIDE / 2) * SCALE);
pl->p_y = my_y + ((y - SPWINSIDE / 2) * SCALE);
#ifdef ROTATERACE
if (rotate) {
rotate_coord(&pl->p_x, &pl->p_y,
rotate_deg, GWIDTH / 2, GWIDTH / 2);
rotate_dir(&pl->p_dir, rotate_deg);
}
#endif
}
} /* for */
}
/* if */
else
#endif /* MAXPLAYER > 32 */
if (sbuf[1] & 64) { /* Short Header */
sbuf += 4;
for (i = 0; i < numofplayers; i++)
{
pl_no = ((unsigned char) *sbuf & 0x1f);
if (pl_no >= MAXPLAYER)
continue;
save = (unsigned char) *sbuf;
sbuf++;
pl = &players[pl_no];
pl->p_speed = (unsigned char) *sbuf & 15; /* SPEED */
#ifdef CLOAK_MAXWARP
if (cloak_maxwarp && pl != me) {
if(pl->p_speed == 15)
pl->p_flags |= PFCLOAK;
else
pl->p_flags &= ~(PFCLOAK);
}
#endif
pl->p_dir = (unsigned char) (*sbuf>>4) * 16; /* realDIR */
sbuf++;
x = (unsigned char) *sbuf++;
y = (unsigned char) *sbuf++; /* The lower 8 Bits are saved */
/* Now we must preprocess the coordinates */
if ((unsigned char) save & 64)
x |= 256;
if ((unsigned char) save & 128)
y |= 256;
#ifdef WARP_DEAD
if (dead_warp && pl->p_speed == 14 && x==-10000 && y==-10000) {
pl->p_status = PEXPLODE;
x = pl->p_x;
y = pl->p_y;
if (pl->p_dir > DEADPACKETS)
pl->p_explode = EX_FRAMES;
else
pl->p_explode = 0;
redrawPlayer[pl->p_no] = updatePlayer[pl->p_no] = 1;
}
#endif
/* Now test if it's galactic or local coord */
if (save & 32) { /* It's galactic */
redrawPlayer[pl->p_no] = 1;
if(x == 501 || y == 501){
x = -500;
y = -500;
}
pl->p_x = x * (GWIDTH / SPWINSIDE);
pl->p_y = y * (GWIDTH / SPWINSIDE);
#ifdef ROTATERACE
if (rotate) {
rotate_coord(&pl->p_x, &pl->p_y,
rotate_deg, GWIDTH / 2, GWIDTH / 2);
rotate_dir(&pl->p_dir, rotate_deg);
}
#endif
} else { /* Local */
redrawPlayer[pl->p_no] = 1;
pl->p_x = my_x + ((x - SPWINSIDE / 2) * SCALE);
pl->p_y = my_y + ((y - SPWINSIDE / 2) * SCALE);
#ifdef ROTATERACE
if (rotate) {
rotate_coord(&pl->p_x, &pl->p_y,
rotate_deg, GWIDTH / 2, GWIDTH / 2);
rotate_dir(&pl->p_dir, rotate_deg);
}
#endif
}
} /* for */
}
/* 2. if */
else { /* Big Packet */
struct player_s_spacket *packet = (struct player_s_spacket *) sbuf;
pl = &players[me->p_no];
pl->p_dir = (unsigned char) packet->dir;
x = htonl(packet->x);
y = htonl(packet->y);
pl->p_speed = packet->speed;
#ifdef WARP_DEAD
if (dead_warp && pl->p_speed == 14 && x==-10000 && y==-10000) {
pl->p_status = PEXPLODE;
x = pl->p_x;
y = pl->p_y;
if (pl->p_dir > DEADPACKETS)
pl->p_explode = EX_FRAMES;
else
pl->p_explode = 0;
redrawPlayer[me->p_no] = updatePlayer[me->p_no] = 1;
}
#endif
#ifdef CLOAK_MAXWARP
if (cloak_maxwarp && pl != me)
{
if(pl->p_speed == 15)
pl->p_flags |= PFCLOAK;
else
pl->p_flags &= ~(PFCLOAK);
}
#endif
pl->p_x = my_x = x;
pl->p_y = my_y = y;
#ifdef ROTATERACE
if (rotate) {
rotate_coord(&pl->p_x, &pl->p_y,
rotate_deg, GWIDTH / 2, GWIDTH / 2);
rotate_dir(&pl->p_dir, rotate_deg);
}
#endif
redrawPlayer[me->p_no] = 1;
if (sbuf[1] == 0)
return;
sbuf += 12; /* Now the small packets */
for (i = 0; i < numofplayers; i++) {
pl_no = ((unsigned char) *sbuf & 0x1f);
if (pl_no >= MAXPLAYER)
continue;
save = (unsigned char) *sbuf;
sbuf++;
pl = &players[pl_no];
pl->p_speed = (unsigned char) *sbuf & 15; /* SPEED */
#ifdef CLOAK_MAXWARP
if (cloak_maxwarp && pl != me) {
if(pl->p_speed == 15)
pl->p_flags |= PFCLOAK;
else
pl->p_flags &= ~(PFCLOAK);
}
#endif
pl->p_dir = (unsigned char) (*sbuf>>4) * 16; /* realDIR */
sbuf++;
x = (unsigned char) *sbuf++;
y = (unsigned char) *sbuf++; /* The lower 8 Bits are saved */
/* Now we must preprocess the coordinates */
if ((unsigned char) save & 64)
x |= 256;
if ((unsigned char) save & 128)
y |= 256;
#ifdef WARP_DEAD
if (dead_warp && pl->p_speed == 14 && x==-10000 && y==-10000) {
pl->p_status = PEXPLODE;
x = pl->p_x;
y = pl->p_y;
if (pl->p_dir > DEADPACKETS)
pl->p_explode = EX_FRAMES;
else
pl->p_explode = 0;
redrawPlayer[pl_no] = updatePlayer[pl_no] = 1;
}
#endif
/* Now test if it's galactic or local coord */
if (save & 32) { /* It's galactic */
redrawPlayer[pl_no] = 1;
if(x == 501 || y == 501){
x = -500;
y = -500;
}
pl->p_x = x * (GWIDTH / SPWINSIDE);
pl->p_y = y * (GWIDTH / SPWINSIDE);
#ifdef ROTATERACE
if (rotate) {
rotate_coord(&pl->p_x, &pl->p_y,
rotate_deg, GWIDTH / 2, GWIDTH / 2);
rotate_dir(&pl->p_dir, rotate_deg);
}
#endif
} else { /* Local */
redrawPlayer[pl_no] = 1;
pl->p_x = my_x + (x - SPWINSIDE / 2) * SCALE;
pl->p_y = my_y + (y - SPWINSIDE / 2) * SCALE;
#ifdef ROTATERACE
if (rotate) {
rotate_coord(&pl->p_x, &pl->p_y,
rotate_deg, GWIDTH / 2, GWIDTH / 2);
rotate_dir(&pl->p_dir, rotate_deg);
}
#endif
}
} /* for */
}
}
#endif /* SHORT_PACKETS */
handleWarning(packet)
struct warning_spacket *packet;
{
packet->mesg[sizeof(packet->mesg) - 1] = '\0'; /* guarantee null
* termination */
warning(packet->mesg);
}
sendShortPacket(type, state)
char type, state;
{
struct speed_cpacket speedReq;
speedReq.type = type;
speedReq.speed = state;
sendServerPacket((struct player_spacket *) & speedReq);
/* if we're sending in UDP mode, be prepared to force it */
if (commMode == COMM_UDP && udpClientSend >= 2) {
switch (type) {
case CP_SPEED:
fSpeed = state | 0x100;
break;
case CP_DIRECTION:
fDirection = state | 0x100;
break;
case CP_SHIELD:
fShield = state | 0xa00;
break;
case CP_ORBIT:
fOrbit = state | 0xa00;
break;
case CP_REPAIR:
fRepair = state | 0xa00;
break;
case CP_CLOAK:
fCloak = state | 0xa00;
break;
case CP_BOMB:
fBomb = state | 0xa00;
break;
case CP_DOCKPERM:
fDockperm = state | 0xa00;
break;
case CP_PLAYLOCK:
fPlayLock = state | 0xa00;
break;
case CP_PLANLOCK:
fPlanLock = state | 0xa00;
break;
case CP_BEAM:
if (state == 1)
fBeamup = 1 | 0x500;
else
fBeamdown = 2 | 0x500;
break;
}
/* force weapons too? */
if (udpClientSend >= 3) {
switch (type) {
case CP_PHASER:
fPhaser = state | 0x100;
break;
case CP_PLASMA:
fPlasma = state | 0x100;
break;
}
}
}
}
sendServerPacket(packet)
/* Pick a random type for the packet */
struct player_spacket *packet;
{
int size;
if (serverDead)
return;
if (packet->type < 1 || packet->type > NUM_SIZES || sizes[packet->type] == 0) {
printf("Attempt to send strange packet %d!\n", packet->type);
return;
}
size = sizes[packet->type];
#ifdef PACKET_LOG
if (log_packets)
Log_OPacket(packet->type,size);
#endif
if (commMode == COMM_UDP) {
/* for now, just sent everything via TCP */
}
if (commMode == COMM_TCP || !udpClientSend) {
/* special case for verify packet */
if (packet->type == CP_UDP_REQ) {
if (((struct udp_req_cpacket *) packet)->request == COMM_VERIFY)
goto send_udp;
}
/*
* business as usual (or player has turned off UDP transmission)
*/
if (gwrite(sock, (char *) packet, size) != size) {
printf("gwrite failed. Server must be dead\n");
serverDead = 1;
}
} else {
/*
* UDP stuff
*/
switch (packet->type) {
case CP_SPEED:
case CP_DIRECTION:
case CP_PHASER:
case CP_PLASMA:
case CP_TORP:
case CP_QUIT:
case CP_PRACTR:
case CP_SHIELD:
case CP_REPAIR:
case CP_ORBIT:
case CP_PLANLOCK:
case CP_PLAYLOCK:
case CP_BOMB:
case CP_BEAM:
case CP_CLOAK:
case CP_DET_TORPS:
case CP_DET_MYTORP:
case CP_REFIT:
case CP_TRACTOR:
case CP_REPRESS:
case CP_COUP:
case CP_DOCKPERM:
#ifdef INCLUDE_SCAN
case CP_SCAN:
#endif
#ifdef PING
case CP_PING_RESPONSE:
#endif
/* non-critical stuff, use UDP */
send_udp:
#ifdef PING
packets_sent++;
#endif
V_UDPDIAG(("Sent %d on UDP port\n", packet->type));
if (gwrite(udpSock, packet, size) != size) {
UDPDIAG(("gwrite on UDP failed. Closing UDP connection\n"));
warning("UDP link severed");
/* serverDead=1; */
commModeReq = commMode = COMM_TCP;
commStatus = STAT_CONNECTED;
commSwitchTimeout = 0;
if (udpWin) {
udprefresh(UDP_STATUS);
udprefresh(UDP_CURRENT);
}
if (udpSock >= 0)
closeUdpConn();
}
break;
default:
/* critical stuff, use TCP */
if (gwrite(sock, (char *) packet, size) != size) {
printf("gwrite failed. Server must be dead\n");
serverDead = 1;
}
}
}
}
handlePlanet(packet)
struct planet_spacket *packet;
{
struct planet *plan;
/* FAT: prevent excessive redraw */
int redraw = 0;
#ifdef CORRUPTED_PACKETS
if (packet->pnum < 0 || packet->pnum >= MAXPLANETS) {
fprintf(stderr, "handlePlanet: bad index %d\n", packet->pnum);
return;
}
#endif
plan = &planets[packet->pnum];
#ifdef nodef
monpoprate(plan, packet);
#endif
if (plan->pl_owner != packet->owner)
redraw = 1;
plan->pl_owner = packet->owner;
if (plan->pl_owner < FED || plan->pl_owner > ORI)
plan->pl_owner = NOBODY;
if (plan->pl_info != packet->info)
redraw = 1;
plan->pl_info = packet->info;
/* Redraw the planet because it was updated by server */
if (plan->pl_flags != (int) ntohs(packet->flags))
redraw = 1;
plan->pl_flags = (int) ntohs(packet->flags);
if (plan->pl_armies != ntohl(packet->armies)) {
#ifdef EM
/*
* don't redraw when armies change unless it crosses the '4' * army
* limit. Keeps people from watching for planet 'flicker' * when
* players are beaming
*/
int planetarmies = ntohl(packet->armies);
if ((plan->pl_armies < 5 && planetarmies > 4) ||
(plan->pl_armies > 4 && planetarmies < 5))
#endif
redraw = 1;
}
plan->pl_armies = ntohl(packet->armies);
if (plan->pl_info == 0) {
plan->pl_owner = NOBODY;
}
if (redraw){
plan->pl_flags |= (PLREDRAW|PLCLEAR);
}
}
handlePhaser(packet)
struct phaser_spacket *packet;
{
struct phaser *phas;
#ifdef CORRUPTED_PACKETS
if (packet->pnum < 0 || packet->pnum >= MAXPLAYER) {
fprintf(stderr, "handlePhaser: bad index %d\n", packet->pnum);
return;
}
if (packet->status == PHHIT &&
(ntohl(packet->target) < 0 || ntohl(packet->target) >= MAXPLAYER)) {
fprintf(stderr, "handlePhaser: bad target %d\n", ntohl(packet->target));
return;
}
#endif
phas = &phasers[packet->pnum];
phas->ph_status = packet->status;
phas->ph_dir = packet->dir;
phas->ph_x = ntohl(packet->x);
phas->ph_y = ntohl(packet->y);
phas->ph_target = ntohl(packet->target);
phas->ph_fuse = 0; /* NEW */
#ifdef ROTATERACE
if (rotate) {
rotate_coord(&phas->ph_x, &phas->ph_y, rotate_deg, GWIDTH / 2, GWIDTH / 2);
rotate_dir(&phas->ph_dir, rotate_deg);
}
#endif
}
handleMessage(packet)
struct mesg_spacket *packet;
{
if (packet->m_from >= MAXPLAYER)
packet->m_from = 255;
#ifdef CORRUPTED_PACKETS
packet->mesg[sizeof(packet->mesg) - 1] = '\0';
#endif
/*
* printf("flags: 0x%x\n", packet->m_flags); printf("from: %d\n",
* packet->m_from); printf("recpt: %d\n", packet->m_recpt); printf("mesg:
* %s\n", packet->mesg);
*/
dmessage(packet->mesg, packet->m_flags, packet->m_from, packet->m_recpt);
}
#ifdef SHORT_PACKETS
handleSMessage(packet)
struct mesg_s_spacket *packet;
{
char buf[100], *bf = buf;
char addrbuf[9];
unsigned char flags;
if (debug)
printf("Length of Message is: %d total Size %d \n", strlen(&packet->mesg), (int) packet->length);
if (packet->m_from >= MAXPLAYER)
packet->m_from = 255;
if (packet->m_from == 255){
strcpy(bf, "GOD->");
bf += 5;
}
else {
*bf++ = ' ';
*bf++ = teamlet[players[packet->m_from].p_team];
*bf++ = shipnos[players[packet->m_from].p_no];
*bf++ = '-';
*bf++ = '>';
}
switch (packet->m_flags & (MTEAM | MINDIV | MALL)) {
case MALL:
bf = strcpy_return(bf, "ALL");
break;
case MTEAM:
bf = strcpy_return(bf, teamshort[me->p_team]);
break;
case MINDIV:
/* I know that it's me -> xxx but i copied it straight ... */
*bf++ = teamlet[players[packet->m_recpt].p_team];
*bf++ = shipnos[packet->m_recpt];
break;
default:
bf = strcpy_return (bf, "ALL");
break;
}
while(bf-buf < 9)
*bf++ = ' ';
strcpy(bf, &packet->mesg);
dmessage(buf, packet->m_flags, packet->m_from, packet->m_recpt);
}
#endif /* SHORT_PACKETS */
handleQueue(packet)
struct queue_spacket *packet;
{
queuePos = ntohs(packet->pos);
}
sendTeamReq(team, ship)
int team, ship;
{
struct outfit_cpacket outfitReq;
outfitReq.type = CP_OUTFIT;
outfitReq.team = team;
outfitReq.ship = ship;
sendServerPacket((struct player_spacket *) & outfitReq);
}
handlePickok(packet)
struct pickok_spacket *packet;
{
pickOk = packet->state;
}
sendLoginReq(name, pass, login, query)
char *name, *pass;
char *login;
char query;
{
struct login_cpacket packet;
strcpy(packet.name, name);
strcpy(packet.password, pass);
if (strlen(login) > 15)
login[15] = 0;
strcpy(packet.login, login);
packet.type = CP_LOGIN;
packet.query = query;
sendServerPacket((struct player_spacket *) & packet);
}
handleLogin(packet)
struct login_spacket *packet;
{
loginAccept = packet->accept;
if ((packet->pad2 == 69) && (packet->pad3 == 42))
{
printf ("Connection Error: this client does not support parardise server protocols.\n");
exit(0);
}
if (packet->accept) {
/*
* no longer needed .. we have it in xtrekrc bcopy(packet->keymap,
* mystats->st_keymap, 96);
*/
mystats->st_flags = ntohl(packet->flags);
showShields = (me->p_stats.st_flags / ST_SHOWSHIELDS) & 1;
#ifndef nodef
mapmode = (me->p_stats.st_flags / ST_MAPMODE) & 1;
#endif
namemode = (me->p_stats.st_flags / ST_NAMEMODE) & 1;
keeppeace = (me->p_stats.st_flags / ST_KEEPPEACE) & 1;
showlocal = (me->p_stats.st_flags / ST_SHOWLOCAL) & 3;
showgalactic = (me->p_stats.st_flags / ST_SHOWGLOBAL) & 3;
}
}
sendTractorReq(state, pnum)
char state;
char pnum;
{
struct tractor_cpacket tractorReq;
tractorReq.type = CP_TRACTOR;
tractorReq.state = state;
tractorReq.pnum = pnum;
sendServerPacket((struct player_spacket *) & tractorReq);
if (state)
fTractor = pnum | 0x40;
else
fTractor = 0;
}
sendRepressReq(state, pnum)
char state;
char pnum;
{
struct repress_cpacket repressReq;
repressReq.type = CP_REPRESS;
repressReq.state = state;
repressReq.pnum = pnum;
sendServerPacket((struct player_spacket *) & repressReq);
if (state)
fRepress = pnum | 0x40;
else
fRepress = 0;
}
sendDetMineReq(torp)
short torp;
{
struct det_mytorp_cpacket detReq;
detReq.type = CP_DET_MYTORP;
detReq.tnum = htons(torp);
sendServerPacket((struct player_spacket *) & detReq);
}
handlePlasmaInfo(packet)
struct plasma_info_spacket *packet;
{
struct plasmatorp *thetorp;
#ifdef CORRUPTED_PACKETS
if (ntohs(packet->pnum) >= MAXPLAYER * MAXPLASMA) {
fprintf(stderr, "handlePlasmaInfo: bad index %d\n", packet->pnum);
return;
}
#endif
thetorp = &plasmatorps[ntohs(packet->pnum)];
if (packet->status == PTEXPLODE && thetorp->pt_status == PTFREE) {
/* FAT: redundant explosion; don't update p_nplasmatorp */
return;
}
if (!thetorp->pt_status && packet->status) {
players[thetorp->pt_owner].p_nplasmatorp++;
}
if (thetorp->pt_status && !packet->status) {
players[thetorp->pt_owner].p_nplasmatorp--;
}
thetorp->pt_war = packet->war;
if (thetorp->pt_status != packet->status) {
/* FAT: prevent explosion timer from being reset */
thetorp->pt_status = packet->status;
if (thetorp->pt_status == PTEXPLODE) {
thetorp->pt_fuse = NUMDETFRAMES;
}
}
}
handlePlasma(packet)
struct plasma_spacket *packet;
{
struct plasmatorp *thetorp;
#ifdef CORRUPTED_PACKETS
if (ntohs(packet->pnum) >= MAXPLAYER * MAXPLASMA) {
fprintf(stderr, "handlePlasma: bad index %d\n", packet->pnum);
return;
}
#endif
thetorp = &plasmatorps[ntohs(packet->pnum)];
thetorp->pt_x = ntohl(packet->x);
thetorp->pt_y = ntohl(packet->y);
#ifdef ROTATERACE
if (rotate) {
rotate_coord(&thetorp->pt_x, &thetorp->pt_y, rotate_deg, GWIDTH / 2, GWIDTH / 2);
}
#endif
}
handleFlags(packet)
struct flags_spacket *packet;
{
#ifdef CORRUPTED_PACKETS
if (packet->pnum < 0 || packet->pnum >= MAXPLAYER) {
fprintf(stderr, "handleFlags: bad index %d\n", packet->pnum);
return;
}
#endif
if (players[packet->pnum].p_flags != ntohl(packet->flags)
#ifdef INCLUDE_VISTRACT
|| players[packet->pnum].p_tractor !=
((short) packet->tractor & (~0x40))
#endif
) {
/* FAT: prevent redundant player update */
redrawPlayer[packet->pnum] = 1;
} else
return;
players[packet->pnum].p_flags = ntohl(packet->flags);
#ifdef INCLUDE_VISTRACT
if (packet->tractor & 0x40)
players[packet->pnum].p_tractor = (short) packet->tractor & (~0x40); /* ATM - visible
* tractors */
else
#endif /* INCLUDE_VISTRACT */
players[packet->pnum].p_tractor = -1;
}
handleKills(packet)
struct kills_spacket *packet;
{
#ifdef CORRUPTED_PACKETS
if (packet->pnum < 0 || packet->pnum >= MAXPLAYER) {
fprintf(stderr, "handleKills: bad index %d\n", packet->pnum);
return;
}
#endif
if (players[packet->pnum].p_kills != ntohl(packet->kills) / 100.0) {
players[packet->pnum].p_kills = ntohl(packet->kills) / 100.0;
/* FAT: prevent redundant player update */
updatePlayer[packet->pnum] = 1;
#ifdef ARMY_SLIDER
if (me == &players[packet->pnum]) {
calibrate_stats();
redrawStats();
}
#endif /* ARMY_SLIDER */
}
}
handlePStatus(packet)
struct pstatus_spacket *packet;
{
register struct player *j;
#ifdef CORRUPTED_PACKETS
if (packet->pnum < 0 || packet->pnum >= MAXPLAYER) {
fprintf(stderr, "handlePStatus: bad index %d\n", packet->pnum);
return;
}
#endif
j = &players[packet->pnum];
if(packet->status == j->p_status) return;
/* guarantees we won't miss the kill message since this is TCP */
if(packet->status == PALIVE && j->p_status != PALIVE)
j->p_kills = 0.;
updatePlayer[packet->pnum] = 1;
if (packet->status == PEXPLODE) {
j->p_explode = 0;
}
/*
* Ignore DEAD status. Instead, we treat it as PEXPLODE. This gives us
* time to animate all the frames necessary for the explosions at our own
* pace.
*/
if (packet->status == PDEAD) {
packet->status = PEXPLODE;
}
j->p_status = packet->status;
redrawPlayer[packet->pnum] = 1;
}
handleMotd(packet)
struct motd_spacket *packet;
{
packet->line[sizeof(packet->line) - 1] = '\0';
newMotdLine(packet->line);
}
sendMessage(mes, group, indiv)
char *mes;
int group, indiv;
{
struct mesg_cpacket mesPacket;
#ifdef SHORT_PACKETS
if (recv_short) {
int size;
size = strlen(mes);
size += 5; /* 1 for '\0', 4 packetheader */
if ((size % 4) != 0)
size += (4 - (size % 4));
mesPacket.pad1 = (char) size;
sizes[CP_S_MESSAGE] = size;
mesPacket.type = CP_S_MESSAGE;
} else
#endif
mesPacket.type = CP_MESSAGE;
mesPacket.group = group;
mesPacket.indiv = indiv;
strncpy(mesPacket.mesg, mes, 80);
/* printf("%s, %d, %d\n",mes,group,indiv);*/
sendServerPacket((struct player_spacket *) & mesPacket);
}
#ifdef SHORT_PACKETS
sendThreshold(v)
unsigned short v;
{
struct threshold_cpacket p;
p.type = CP_S_THRS;
p.thresh = v;
sendServerPacket((struct player_spacket *) & p);
}
#endif
handleMask(packet)
struct mask_spacket *packet;
{
tournMask = packet->mask;
}
sendOptionsPacket()
{
struct options_cpacket optPacket;
optPacket.type = CP_OPTIONS;
optPacket.flags =
htonl(ST_MAPMODE * (mapmode != 0) +
ST_NAMEMODE * namemode +
ST_SHOWSHIELDS * showShields +
ST_KEEPPEACE * keeppeace +
ST_SHOWLOCAL * showlocal +
ST_SHOWGLOBAL * showgalactic);
/* just in case - jn - hope all servers can deal with 0 */
MZERO (optPacket.keymap, 96);
sendServerPacket((struct player_spacket *) & optPacket);
}
pickSocket(old)
int old;
{
int newsocket;
struct socket_cpacket sockPack;
newsocket = (getpid() & 32767);
while (newsocket < 2048 || newsocket == old) {
newsocket = (newsocket + 10687) & 32767;
}
sockPack.type = CP_SOCKET;
sockPack.socket = htonl(newsocket);
sockPack.version = (char) SOCKVERSION;
sockPack.udp_version = (char) UDPVERSION;
sendServerPacket((struct player_spacket *) & sockPack);
/* Did we get new socket # sent? */
if (serverDead)
return;
nextSocket = newsocket;
}
handleBadVersion(packet)
struct badversion_spacket *packet;
{
switch (packet->why) {
case 0:
printf("Sorry, this is an invalid client version.\n");
printf("You need a new version of the client code.\n");
break;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
printf("Sorry, but you cannot play xtrek now.\n");
printf("Try again later.\n");
break;
default:
printf("Unknown message from handleBadVersion.\n");
return;
}
exit(1);
}
gwrite(fd, buf, bytes)
int fd;
char *buf;
register int bytes;
{
LONG orig = bytes;
register LONG n;
while (bytes) {
n = write(fd, buf, bytes);
if (n < 0) {
if (fd == udpSock) {
fprintf(stderr, "Tried to write %d, 0x%x, %d\n",
fd, buf, bytes);
perror("write");
printUdpInfo();
}
return (-1);
}
bytes -= n;
buf += n;
}
return (orig);
}
handleHostile(packet)
struct hostile_spacket *packet;
{
register struct player *pl;
#ifdef CORRUPTED_PACKETS
if (packet->pnum < 0 || packet->pnum >= MAXPLAYER) {
fprintf(stderr, "handleHostile: bad index %d\n", packet->pnum);
return;
}
#endif
pl = &players[packet->pnum];
if (pl->p_swar != packet->war ||
pl->p_hostile != packet->hostile) {
/* FAT: prevent redundant player update & redraw */
pl->p_swar = packet->war;
pl->p_hostile = packet->hostile;
updatePlayer[packet->pnum] = 1;
redrawPlayer[packet->pnum] = 1;
}
}
handlePlyrLogin(packet
#ifdef CORRUPTED_PACKETS
,sock
#endif
)
struct plyr_login_spacket *packet;
{
register struct player *pl;
#ifdef CORRUPTED_PACKETS
if (sock == udpSock) {
fprintf(stderr, "garbage packet discarded.\n");
return;
}
#endif
#ifdef CORRUPTED_PACKETS
if (packet->pnum < 0 || packet->pnum >= MAXPLAYER) {
fprintf(stderr, "handlePlyrLogin: bad index %d\n", packet->pnum);
return;
}
if (packet->rank < 0 || packet->rank >= NUMRANKS) {
fprintf(stderr, "handlePlyrLogin: bad rank %d\n", packet->rank);
return;
}
packet->name[sizeof(packet->name) - 1] = '\0';
packet->monitor[sizeof(packet->monitor) - 1] = '\0';
packet->login[sizeof(packet->login) - 1] = '\0';
#endif
updatePlayer[packet->pnum] = 1;
pl = &players[packet->pnum];
strcpy(pl->p_name, packet->name);
strcpyp_return(pl->p_monitor, packet->monitor, sizeof(pl->p_monitor));
strcpy(pl->p_login, packet->login);
pl->p_stats.st_rank = packet->rank;
/*
* printf("read player login %s, %s, %s\n", pl->p_name, pl->p_monitor,
* pl->p_login);
*/
if (packet->pnum == me->p_no) {
/* This is me. Set some stats */
if (lastRank == -1) {
if (loggedIn) {
lastRank = packet->rank;
}
} else {
if (lastRank != packet->rank) {
lastRank = packet->rank;
promoted = 1;
}
}
}
}
handleStats(packet)
struct stats_spacket *packet;
{
register struct player *pl;
#ifdef CORRUPTED_PACKETS
if (packet->pnum < 0 || packet->pnum >= MAXPLAYER)
{
fprintf(stderr, "handleStats: bad index %d\n", packet->pnum);
return;
}
#endif
pl = &players[packet->pnum];
#ifdef NEW_PL
/* only update if p_kills change since that's the only stat we
show */
if(!newPlist)
#endif
updatePlayer[packet->pnum] = 1;
pl->p_stats.st_tkills = ntohl(packet->tkills);
pl->p_stats.st_tlosses = ntohl(packet->tlosses);
pl->p_stats.st_kills = ntohl(packet->kills);
pl->p_stats.st_losses = ntohl(packet->losses);
pl->p_stats.st_tticks = ntohl(packet->tticks);
pl->p_stats.st_tplanets = ntohl(packet->tplanets);
pl->p_stats.st_tarmsbomb = ntohl(packet->tarmies);
pl->p_stats.st_sbkills = ntohl(packet->sbkills);
pl->p_stats.st_sblosses = ntohl(packet->sblosses);
pl->p_stats.st_armsbomb = ntohl(packet->armies);
pl->p_stats.st_planets = ntohl(packet->planets);
#ifdef SBHOURS
if ((pl->p_ship.s_type == STARBASE) && (SBhours))
{
pl->p_stats.st_sbticks = ntohl (packet->maxkills);
}
else
{
pl->p_stats.st_maxkills = ntohl (packet->maxkills) / 100.0;
}
#else
pl->p_stats.st_maxkills = ntohl(packet->maxkills) / 100.0;
#endif
pl->p_stats.st_sbmaxkills = ntohl(packet->sbmaxkills) / 100.0;
}
handlePlyrInfo(packet)
struct plyr_info_spacket *packet;
{
register struct player *pl;
static int lastship = -1;
#ifdef CORRUPTED_PACKETS
if (packet->pnum < 0 || packet->pnum >= MAXPLAYER) {
fprintf(stderr, "handlePlyrInfo: bad index %d\n", packet->pnum);
return;
}
if (packet->team < 0 || packet->team > ALLTEAM) {
fprintf(stderr, "handlePlyrInfo: bad team %d\n", packet->team);
return;
}
#endif
updatePlayer[packet->pnum] = 1;
pl = &players[packet->pnum];
getship(&pl->p_ship, packet->shiptype);
pl->p_team = packet->team;
pl->p_mapchars[0] = teamlet[pl->p_team];
pl->p_mapchars[1] = shipnos[pl->p_no];
if (me == pl && lastship != me->p_ship.s_type) {
redrawTstats();
calibrate_stats();
redrawStats(); /* TSH */
}
redrawPlayer[packet->pnum] = 1;
}
sendUpdatePacket(speed)
LONG speed;
{
struct updates_cpacket packet;
packet.type = CP_UPDATES;
timerDelay = speed;
packet.usecs = htonl(speed);
sendServerPacket((struct player_spacket *) & packet);
}
handlePlanetLoc(packet)
struct planet_loc_spacket *packet;
{
struct planet *pl;
#ifdef CORRUPTED_PACKETS
if (packet->pnum < 0 || packet->pnum >= MAXPLANETS) {
fprintf(stderr, "handlePlanetLoc: bad index\n");
return;
}
#endif
pl = &planets[packet->pnum];
pl_update[packet->pnum].plu_x = pl->pl_x;
pl_update[packet->pnum].plu_y = pl->pl_y;
if (pl_update[packet->pnum].plu_update != -1) {
pl_update[packet->pnum].plu_update = 1;
/*
* printf("update: %s, old (%d,%d) new (%d,%d)\n", pl->pl_name,
* pl->pl_x, pl->pl_y, ntohl(packet->x),ntohl(packet->y));
*/
} else
pl_update[packet->pnum].plu_update = 0;
pl->pl_x = ntohl(packet->x);
pl->pl_y = ntohl(packet->y);
strcpy(pl->pl_name, packet->name);
pl->pl_namelen = strlen(packet->name);
pl->pl_flags |= (PLREDRAW|PLCLEAR);
reinitPlanets = 1;
#ifdef ROTATERACE
if (rotate) {
rotate_coord(&pl->pl_x, &pl->pl_y, rotate_deg, GWIDTH / 2, GWIDTH / 2);
}
#endif
}
handleReserved(packet
#ifdef CORRUPTED_PACKETS
,sock
#endif
)
struct reserved_spacket *packet;
{
struct reserved_cpacket response;
#ifdef CORRUPTED_PACKETS
if (sock == udpSock) {
fprintf(stderr, "garbage Reserved packet discarded.\n");
return;
}
#endif
#ifdef FOR_MORONS
{ /* it _is_ an 'info' borg, after all. ;-) */
extern int For_Morons;
if (For_Morons)
return;
}
#endif
#if !defined(BORG)
#ifndef RSA
encryptReservedPacket(packet, &response, serverName, me->p_no);
sendServerPacket((struct player_spacket *) & response);
#else
if (RSA_Client) { /* can use -o option for old blessing */
/* client sends back a 'reserved' packet just saying RSA_VERSION info */
/*
* theoretically, the server then sends off a rsa_key_spacket * for the
* client to then respond to
*/
warning(RSA_VERSION);
strncpy(response.resp, RSA_VERSION, RESERVED_SIZE);
bcopy(packet->data, response.data, RESERVED_SIZE);
response.type = CP_RESERVED;
#ifdef DEBUG
printf("Sending RSA reserved response\n");
#endif
} else{
#ifdef FEATURE
/* If server gods don't like NEWMACRO/SMARTMACRO
they better install RSA... */
F_UseNewMacro = 1;
F_UseSmartMacro = 1;
#endif
encryptReservedPacket(packet, &response, serverName, me->p_no);
}
sendServerPacket(&response);
#endif /* RSA */
#endif /* defined(BORG) */
}
#ifdef RSA
handleRSAKey(packet)
struct rsa_key_spacket *packet;
{
struct rsa_key_cpacket response;
struct sockaddr_in saddr;
u_short port;
unsigned char* data;
int len;
struct timeval start, end;
#ifdef GATEWAY
extern unsigned LONG netaddr;
extern int serv_port;
#endif
#ifdef GATEWAY
/* if we didn't get it from -H, go ahead and query the socket */
if (netaddr == 0) {
len = sizeof(saddr);
if (getpeername(sock,(struct sockaddr*)&saddr, &len) < 0) {
perror("getpeername(sock)");
exit(1);
}
} else {
saddr.sin_addr.s_addr = netaddr;
saddr.sin_port = htons(serv_port);
}
#else
/* query the socket to determine the remote host (ATM) */
len = sizeof(saddr);
if (getpeername(sock,(struct sockaddr*) &saddr, &len) < 0) {
perror("getpeername(sock)");
exit(1);
}
#endif
data = packet->data;
bcopy(&saddr.sin_addr.s_addr, data, sizeof(saddr.sin_addr.s_addr));
data += sizeof(saddr.sin_addr.s_addr);
bcopy(&saddr.sin_port, data, sizeof(saddr.sin_port));
gettimeofday(&start, NULL);
rsa_black_box(response.resp, packet->data,
response.public, response.global);
gettimeofday(&end, NULL);
printf("rsa_black_box took %d ms.\n",
(1000 * (end.tv_sec - start.tv_sec) +
(end.tv_usec - start.tv_usec) / 1000));
response.type = CP_RSA_KEY;
#ifdef FEATURE
if (report_features)
reportFeatures ();
#endif
sendServerPacket(&response);
/* #ifdef DEBUG */
printf("RSA verification requested.\n");
/* #endif */
}
#endif
#ifdef INCLUDE_SCAN
handleScan(packet)
struct scan_spacket *packet;
{
struct player *pp;
#ifdef CORRUPTED_PACKETS
if (packet->pnum < 0 || packet->pnum >= MAXPLAYER) {
fprintf(stderr, "handleScan: bad index\n");
return;
}
#endif
if (packet->success) {
pp = &players[packet->pnum];
pp->p_fuel = ntohl(packet->p_fuel);
pp->p_armies = ntohl(packet->p_armies);
pp->p_shield = ntohl(packet->p_shield);
pp->p_damage = ntohl(packet->p_damage);
pp->p_etemp = ntohl(packet->p_etemp);
pp->p_wtemp = ntohl(packet->p_wtemp);
informScan(packet->pnum);
}
}
informScan(p)
int p;
{
}
#endif /* INCLUDE_SCAN */
/*
* UDP stuff
*/
sendUdpReq(req)
int req;
{
struct udp_req_cpacket packet;
packet.type = CP_UDP_REQ;
packet.request = req;
if (req >= COMM_MODE) {
packet.request = COMM_MODE;
packet.connmode = req - COMM_MODE;
sendServerPacket(&packet);
return;
}
if (req == COMM_UPDATE) {
#ifdef SHORT_PACKETS
if (recv_short) { /* not necessary */
/* Let the client do the work, and not the network :-) */
register int i;
for (i = 0; i < MAXPLAYER * MAXTORP; i++)
torps[i].t_status = TFREE;
for (i = 0; i < MAXPLAYER * MAXPLASMA; i++)
plasmatorps[i].pt_status = PTFREE;
for (i = 0; i < MAXPLAYER; i++) {
players[i].p_ntorp = 0;
players[i].p_nplasmatorp = 0;
phasers[i].ph_status = PHFREE;
}
}
#endif
sendServerPacket(&packet);
warning("Sent request for full update");
return;
}
if (req == commModeReq) {
warning("Request is in progress, do not disturb");
return;
}
if (req == COMM_UDP) {
/* open UDP port */
if (openUdpConn() >= 0) {
UDPDIAG(("Bound to local port %d on fd %d\n", udpLocalPort, udpSock));
} else {
UDPDIAG(("Bind to local port %d failed\n", udpLocalPort));
commModeReq = COMM_TCP;
commStatus = STAT_CONNECTED;
commSwitchTimeout = 0;
if (udpWin)
udprefresh(UDP_STATUS);
warning("Unable to establish UDP connection");
return;
}
}
/* send the request */
packet.type = CP_UDP_REQ;
packet.request = req;
packet.port = htonl(udpLocalPort);
#ifdef GATEWAY
if (!strcmp(serverName, gw_mach)) {
packet.port = htons(gw_serv_port); /* gw port that server should
* call */
UDPDIAG(("+ Telling server to contact us on %d\n", gw_serv_port));
}
#endif
#ifdef USE_PORTSWAP
packet.connmode = CONNMODE_PORT; /* have him send his port */
#else
packet.connmode = CONNMODE_PACKET; /* we get addr from packet */
#endif
sendServerPacket((struct player_spacket *) & packet);
/* update internal state stuff */
commModeReq = req;
if (req == COMM_TCP)
commStatus = STAT_SWITCH_TCP;
else
commStatus = STAT_SWITCH_UDP;
commSwitchTimeout = 25; /* wait 25 updates (about five seconds) */
UDPDIAG(("Sent request for %s mode\n", (req == COMM_TCP) ?
"TCP" : "UDP"));
#ifndef USE_PORTSWAP
if ((req == COMM_UDP) && recvUdpConn() < 0) {
UDPDIAG(("Sending TCP reset message\n"));
packet.request = COMM_TCP;
packet.port = 0;
commModeReq = COMM_TCP;
sendServerPacket((struct player_spacket *) & packet);
/* we will likely get a SWITCH_UDP_OK later; better ignore it */
commModeReq = COMM_TCP;
commStatus = STAT_CONNECTED;
commSwitchTimeout = 0;
}
#endif
if (udpWin)
udprefresh(UDP_STATUS);
}
handleUdpReply(packet)
struct udp_reply_spacket *packet;
{
struct udp_req_cpacket response;
UDPDIAG(("Received UDP reply %d\n", packet->reply));
commSwitchTimeout = 0;
response.type = CP_UDP_REQ;
switch (packet->reply) {
case SWITCH_TCP_OK:
if (commMode == COMM_TCP) {
UDPDIAG(("Got SWITCH_TCP_OK while in TCP mode; ignoring\n"));
} else {
commMode = COMM_TCP;
commStatus = STAT_CONNECTED;
warning("Switched to TCP-only connection");
closeUdpConn();
UDPDIAG(("UDP port closed\n"));
if (udpWin) {
udprefresh(UDP_STATUS);
udprefresh(UDP_CURRENT);
}
}
break;
case SWITCH_UDP_OK:
if (commMode == COMM_UDP) {
UDPDIAG(("Got SWITCH_UDP_OK while in UDP mode; ignoring\n"));
} else {
/* the server is forcing UDP down our throat? */
if (commModeReq != COMM_UDP) {
UDPDIAG(("Got unsolicited SWITCH_UDP_OK; ignoring\n"));
} else {
#ifdef USE_PORTSWAP
udpServerPort = ntohl(packet->port);
if (connUdpConn() < 0) {
UDPDIAG(("Unable to connect, resetting\n"));
warning("Connection attempt failed");
commModeReq = COMM_TCP;
commStatus = STAT_CONNECTED;
if (udpSock >= 0)
closeUdpConn();
if (udpWin) {
udprefresh(UDP_STATUS);
udprefresh(UDP_CURRENT);
}
response.request = COMM_TCP;
response.port = 0;
goto send;
}
#else
/* this came down UDP, so we MUST be connected */
/* (do the verify thing anyway just for kicks) */
#endif
UDPDIAG(("Connected to server's UDP port\n"));
commStatus = STAT_VERIFY_UDP;
if (udpWin)
udprefresh(UDP_STATUS);
response.request = COMM_VERIFY; /* send verify request on UDP */
response.port = 0;
commSwitchTimeout = 25; /* wait 25 updates */
send:
sendServerPacket((struct player_spacket *) & response);
}
}
break;
case SWITCH_DENIED:
if (ntohs(packet->port)) {
UDPDIAG(("Switch to UDP failed (different version)\n"));
warning("UDP protocol request failed (bad version)");
} else {
UDPDIAG(("Switch to UDP denied\n"));
warning("UDP protocol request denied");
}
commModeReq = commMode;
commStatus = STAT_CONNECTED;
commSwitchTimeout = 0;
if (udpWin)
udprefresh(UDP_STATUS);
if (udpSock >= 0)
closeUdpConn();
break;
case SWITCH_VERIFY:
UDPDIAG(("Received UDP verification\n"));
break;
default:
fprintf(stderr, "netrek: Got funny reply (%d) in UDP_REPLY packet\n",
packet->reply);
break;
}
}
#define MAX_PORT_RETRY 10
openUdpConn()
{
struct sockaddr_in addr;
struct hostent *hp;
int attempts;
if (udpSock >= 0) {
fprintf(stderr, "netrek: tried to open udpSock twice\n");
return (0); /* pretend we succeeded (this could be bad) */
}
if ((udpSock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("netrek: unable to create DGRAM socket");
return (-1);
}
#ifdef nodef
set_udp_opts(udpSock);
#endif /* nodef */
if(udpSock >= max_fd)
max_fd = udpSock+1;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_family = AF_INET;
errno = 0;
#ifdef USE_TR_PORTS
if (useTRPorts)
udpLocalPort = 33400;
else
udpLocalPort = (getpid() & 32767) + (random() % 256);
#else
udpLocalPort = (getpid() & 32767) + (random() % 256);
#endif
for (attempts = 0; attempts < MAX_PORT_RETRY; attempts++) {
while (udpLocalPort < 2048) {
udpLocalPort = (udpLocalPort + 10687) & 32767;
}
#ifdef GATEWAY
/* we need the gateway to know where to find us */
if (!strcmp(serverName, gw_mach)) {
UDPDIAG(("+ gateway test: binding to %d\n", gw_local_port));
udpLocalPort = gw_local_port;
}
#endif
addr.sin_port = htons(udpLocalPort);
if (bind(udpSock, &addr, sizeof(addr)) >= 0)
break;
}
if (attempts == MAX_PORT_RETRY) {
perror("netrek: bind");
UDPDIAG(("Unable to find a local port to bind to\n"));
close(udpSock);
udpSock = -1;
return (-1);
}
UDPDIAG(("Local port is %d\n", udpLocalPort));
/* determine the address of the server */
if (!serveraddr) {
if ((addr.sin_addr.s_addr = inet_addr(serverName)) == -1) {
if ((hp = gethostbyname(serverName)) == NULL) {
printf("Who is %s?\n", serverName);
exit(0);
} else {
addr.sin_addr.s_addr = *(LONG *) hp->h_addr;
}
}
serveraddr = addr.sin_addr.s_addr;
UDPDIAG(("Found serveraddr == 0x%x\n", serveraddr));
}
return (0);
}
#ifdef USE_PORTSWAP
connUdpConn()
{
struct sockaddr_in addr;
int len;
addr.sin_addr.s_addr = serveraddr;
addr.sin_family = AF_INET;
addr.sin_port = htons(udpServerPort);
UDPDIAG(("Connecting to host 0x%x on port %d\n", serveraddr, udpServerPort));
if (connect(udpSock, &addr, sizeof(addr)) < 0) {
fprintf(stderr, "Error %d: ");
perror("netrek: unable to connect UDP socket");
printUdpInfo(); /* debug */
return (-1);
}
#ifdef nodef
len = sizeof(addr);
if (getsockname(udpSock, &addr, &len) < 0) {
perror("netrek: unable to getsockname(UDP)");
UDPDIAG(("Can't get our own socket; connection failed\n"));
close(udpSock);
udpSock = -1;
return -1;
}
printf("udpLocalPort %d, getsockname port %d\n",
udpLocalPort, addr.sin_port);
#endif
return (0);
}
#endif
#ifndef USE_PORTSWAP
recvUdpConn()
{
fd_set readfds;
struct timeval to;
struct sockaddr_in from;
struct sockaddr_in addr;
int fromlen, res;
int i;
bzero(&from, sizeof(from)); /* don't get garbage if really broken */
ns_init(3);
/* we patiently wait until the server sends a packet to us */
/* (note that we silently eat the first one) */
UDPDIAG(("Issuing recvfrom() call\n"));
printUdpInfo();
fromlen = sizeof(from);
tryagain:
FD_ZERO(&readfds);
FD_SET(udpSock, &readfds);
to.tv_sec = 6; /* wait 3 seconds, then abort */
to.tv_usec = 0;
if ((res = select(max_fd, &readfds, 0, 0, &to)) <= 0) {
if (!res) {
UDPDIAG(("timed out waiting for response"));
warning("UDP connection request timed out");
return (-1);
} else {
perror("select() before recvfrom()");
return (-1);
}
}
if (recvfrom(udpSock, buf, BUFSIZE, 0, &from, &fromlen) < 0) {
perror("recvfrom");
UDPDIAG(("recvfrom failed, aborting UDP attempt"));
return (-1);
}
if (from.sin_addr.s_addr != serveraddr) {
/* safe? */
serveraddr = from.sin_addr.s_addr;
UDPDIAG(("Warning: from 0x%x, but server is 0x%x\n",
from.sin_addr.s_addr, serveraddr));
}
if (from.sin_family != AF_INET) {
UDPDIAG(("Warning: not AF_INET (%d)\n", from.sin_family));
}
udpServerPort = ntohs(from.sin_port);
UDPDIAG(("recvfrom() succeeded; will use server port %d\n", udpServerPort));
#ifdef GATEWAY
if (!strcmp(serverName, gw_mach)) {
UDPDIAG(("+ actually, I'm going to use %d\n", gw_port));
udpServerPort = gw_port;
from.sin_port = htons(udpServerPort);
}
#endif
if (connect(udpSock, &from, sizeof(from)) < 0) {
perror("netrek: unable to connect UDP socket after recvfrom()");
close(udpSock);
udpSock = -1;
return (-1);
}
return (0);
}
#endif
closeUdpConn()
{
V_UDPDIAG(("Closing UDP socket\n"));
if (udpSock < 0) {
fprintf(stderr, "netrek: tried to close a closed UDP socket\n");
return (-1);
}
shutdown(udpSock, 2);
close(udpSock);
udpSock = -1;
return 0;
}
printUdpInfo()
{
struct sockaddr_in addr;
int len;
len = sizeof(addr);
if (getsockname(udpSock, &addr, &len) < 0) {
/* perror("printUdpInfo: getsockname"); */
return;
}
UDPDIAG(("LOCAL: addr=0x%x, family=%d, port=%d\n", addr.sin_addr.s_addr,
addr.sin_family, ntohs(addr.sin_port)));
if (getpeername(udpSock, &addr, &len) < 0) {
/* perror("printUdpInfo: getpeername"); */
return;
}
UDPDIAG(("PEER : addr=0x%x, family=%d, port=%d\n", addr.sin_addr.s_addr,
addr.sin_family, ntohs(addr.sin_port)));
}
handleSequence(packet)
struct sequence_spacket *packet;
{
static int recent_count = 0, recent_dropped = 0;
LONG newseq;
drop_flag = 0;
if (chan != udpSock)
return; /* don't pay attention to TCP sequence #s */
udpTotal++;
recent_count++;
/* update percent display every 256 updates (~50 seconds usually) */
if (!(udpTotal & 0xff))
if (udpWin)
udprefresh(UDP_DROPPED);
newseq = (LONG) ntohs(packet->sequence);
/* printf("read %d - ", newseq); */
if (((unsigned short) sequence) > 65000 &&
((unsigned short) newseq) < 1000) {
/* we rolled, set newseq = 65536+sequence and accept it */
sequence = ((sequence + 65536) & 0xffff0000) | newseq;
} else {
/* adjust newseq and do compare */
newseq |= (sequence & 0xffff0000);
if (!udpSequenceChk) { /* put this here so that turning seq check */
sequence = newseq; /* on and off doesn't make us think we lost */
return; /* a whole bunch of packets. */
}
if (newseq > sequence) {
/* accept */
if (newseq != sequence + 1) {
udpDropped += (newseq - sequence) - 1;
udpTotal += (newseq - sequence) - 1; /* want TOTAL packets */
recent_dropped += (newseq - sequence) - 1;
recent_count += (newseq - sequence) - 1;
if (udpWin)
udprefresh(UDP_DROPPED);
UDPDIAG(("sequence=%d, newseq=%d, we lost some\n",
sequence, newseq));
}
sequence = newseq;
} else {
/* reject */
if (packet->type == SP_SC_SEQUENCE) {
V_UDPDIAG(("(ignoring repeat %d)\n", newseq));
} else {
UDPDIAG(("sequence=%d, newseq=%d, ignoring transmission\n",
sequence, newseq));
}
#ifdef PING
/*
* the remaining packets will be dropped and we shouldn't count the
* SP_SEQUENCE packet either
*/
packets_received--;
#endif
drop_flag = 1;
}
}
/* printf("newseq %d, sequence %d\n", newseq, sequence); */
if (recent_count > UDP_RECENT_INTR) {
/* once a minute (at 5 upd/sec), report on how many were dropped */
/* during the last UDP_RECENT_INTR updates */
udpRecentDropped = recent_dropped;
recent_count = recent_dropped = 0;
if (udpWin)
udprefresh(UDP_DROPPED);
}
}
#ifdef SHORT_PACKETS
handleShortReply(packet)
struct shortreply_spacket *packet;
{
switch (packet->repl) {
case SPK_VOFF:
recv_short = recv_short_opt = 0;
optionredrawoption(&recv_short_opt);
break;
case SPK_VON:
recv_short = recv_short_opt = 1;
optionredrawoption(&recv_short_opt);
spwinside = ntohs(packet->winside);
spgwidth = ntohl(packet->gwidth);
break;
case SPK_THRESHOLD:
break;
default:
fprintf(stderr, "%s: unknown response packet value short-req: %d\n",
"netrek", packet->repl);
}
}
handleVTorpInfo(sbuf)
unsigned char *sbuf;
{
unsigned char *bitset, *which, *data, *infobitset, *infodata;
struct torp *thetorp;
int dx, dy;
int shiftvar;
char status, war;
register int i;
register int shift = 0; /* How many torps are extracted (for shifting
* ) */
/* now we must find the data ... :-) */
bitset = &sbuf[1];
which = &sbuf[2];
infobitset = &sbuf[3];
/* Where is the data ? */
data = &sbuf[4];
infodata = &sbuf[vtisize[numofbits[(unsigned char) sbuf[1]]]];
#ifdef CORRUPTED_PACKETS
/* we probably should do something clever here - jmn */
if(*which * 8 >= MAXPLAYER * MAXTORP){
fprintf(stderr, "handleVTorp: bad index %d\n", *which * 8);
return;
}
#endif
thetorp = &torps[((unsigned char) *which * 8)];
for (shift = 0, i = 0; /* (unsigned char)*infobitset !=0 ||
(unsigned char )*bitset != 0 */ i < 8;
thetorp++,
*bitset >>= 1,
*infobitset >>= 1,
i++) {
if (*bitset & 01) {
dx = (*data >> shift);
data++;
shiftvar = (unsigned char) *data; /* to silence gcc */
shiftvar <<= (8 - shift);
dx |= (shiftvar & 511);
shift++;
dy = (*data >> shift);
data++;
shiftvar = (unsigned char) *data; /* to silence gcc */
shiftvar <<= (8 - shift);
dy |= (shiftvar & 511);
shift++;
if (shift == 8) {
shift = 0;
data++;
}
/*
* Check for torp with no TorpInfo ( In case we missed a n
* updateAll)
*/
if (!(*infobitset & 01)) {
if (thetorp->t_status == TFREE) {
thetorp->t_status = TMOVE; /* guess */
players[thetorp->t_owner].p_ntorp++;
}
else if (thetorp->t_owner == me->p_no &&
thetorp->t_status == TEXPLODE)
thetorp->t_status = TMOVE;
}
/* Check if torp is visible */
if (dx > SPWINSIDE || dy > SPWINSIDE) {
thetorp->t_x = -100000; /* Not visible */
thetorp->t_y = -100000;
} else { /* visible */
thetorp->t_x = my_x + ((dx - SPWINSIDE / 2) *
SCALE);
thetorp->t_y = my_y + ((dy - SPWINSIDE / 2) *
SCALE);
#ifdef ROTATERACE
if (rotate) {
rotate_coord(&thetorp->t_x, &thetorp->t_y, rotate_deg,
GWIDTH / 2, GWIDTH / 2);
}
#endif
}
}
/* if */
else { /* Got a TFREE ? */
if (!(*infobitset & 01)) { /* No other TorpInfo for this Torp */
/* tsh */
if (thetorp->t_status && thetorp->t_status != TEXPLODE) {
players[thetorp->t_owner].p_ntorp--;
thetorp->t_status = TFREE; /* That's no guess */
}
}
}
/* Now the TorpInfo */
if (*infobitset & 01) {
war = (unsigned char) *infodata & 15 /* 0x0f */ ;
status = ((unsigned char) *infodata & 0xf0) >> 4;
infodata++;
/*
if(status == TEXPLODE)
printf("explode fuse set %d, status: %d, %d\n", thetorp->t_no,
thetorp->t_status, __LINE__);
if(thetorp->t_status == TEXPLODE && status == TFREE)
printf("we have a reset %d\n", __LINE__);
*/
if (status == TEXPLODE && thetorp->t_status == TFREE) {
/* FAT: redundant explosion; don't update p_ntorp */
continue;
}
if (thetorp->t_status == TFREE && status) {
players[thetorp->t_owner].p_ntorp++;
}
if (thetorp->t_status && status == TFREE) {
players[thetorp->t_owner].p_ntorp--;
}
thetorp->t_war = war;
if (status != thetorp->t_status) {
/* FAT: prevent explosion reset */
thetorp->t_status = status;
if (thetorp->t_status == TEXPLODE) {
thetorp->t_fuse = NUMDETFRAMES;
}
/*
if (thetorp->t_status == TFREE)
printf("torp freed %d, %d\n", thetorp->t_no, __LINE__);
*/
}
} /* if */
} /* for */
}
handleVPlanet(sbuf)
unsigned char *sbuf;
{
register int i;
register int numofplanets;/* How many Planets are in the packet */
struct planet *plan;
struct planet_s_spacket *packet = (struct planet_s_spacket *) & sbuf[2];
/* FAT: prevent excessive redraw */
int redraw = 0;
numofplanets = (unsigned char) sbuf[1];
if (numofplanets > MAXPLANETS + 1)
return;
for (i = 0; i < numofplanets; i++, packet++) {
if (packet->pnum < 0 || packet->pnum >= MAXPLANETS)
continue;
plan = &planets[packet->pnum];
if (plan->pl_owner != packet->owner)
redraw = 1;
plan->pl_owner = packet->owner;
if (plan->pl_owner < FED || plan->pl_owner > ORI)
plan->pl_owner = NOBODY;
if (plan->pl_info != packet->info)
redraw = 1;
plan->pl_info = packet->info;
/* Redraw the planet because it was updated by server */
if (plan->pl_flags != (int) ntohs(packet->flags))
redraw = 1;
plan->pl_flags = (int) ntohs(packet->flags);
if (plan->pl_armies != (unsigned char) packet->armies) {
#ifdef EM
/*
* don't redraw when armies change unless it crosses the '4' * army
* limit. Keeps people from watching for planet 'flicker' * when
* players are beaming
*/
int planetarmies = (unsigned char) packet->armies;
if ((plan->pl_armies < 5 && planetarmies > 4) ||
(plan->pl_armies > 4 && planetarmies < 5))
#endif
redraw = 1;
}
plan->pl_armies = (unsigned char) packet->armies;
if (plan->pl_info == 0) {
plan->pl_owner = NOBODY;
}
if (redraw)
plan->pl_flags |= (PLREDRAW|PLCLEAR);
} /* FOR */
}
sendShortReq(state)
char state;
{
struct shortreq_cpacket shortReq;
shortReq.type = CP_S_REQ;
shortReq.req = state;
shortReq.version = SHORTVERSION;
switch (state) {
case SPK_VON:
warning("Sending short packet request");
break;
case SPK_VOFF:
warning("Sending old packet request");
break;
default:
break;
}
if ((state == SPK_SALL || state == SPK_ALL) && recv_short) {
/* Let the client do the work, and not the network :-) */
register int i;
for (i = 0; i < MAXPLAYER * MAXTORP; i++)
torps[i].t_status = TFREE;
for (i = 0; i < MAXPLAYER * MAXPLASMA; i++)
plasmatorps[i].pt_status = PTFREE;
for (i = 0; i < MAXPLAYER; i++) {
players[i].p_ntorp = 0;
players[i].p_nplasmatorp = 0;
phasers[i].ph_status = PHFREE;
}
warning("Sent request for small update");
}
sendServerPacket((struct shortreq_cpacket *) & shortReq);
}
#endif
#ifdef PACKET_LOG
static int Max_CPS = 0;
static int Max_CPSout = 0;
static time_t Start_Time = 0;
static double s2 = 0;
static int sumpl = 0;
static int numpl = 0;
static int outdata_this_sec = 0;
static double sout2 = 0;
static int sumout = 0;
/* HW clumsy but who cares ... :-) */
static int vari_sizes[NUM_PACKETS];
static int cp_msg_size; /* For CP_S_MESSAGE */
int
Log_Packet(type, act_size)
char type;
int act_size; /* HW */
{
static time_t lasttime;
static int data_this_sec;
time_t this_sec;
if (log_packets == 0)
return;
if (type <= 0 && type > NUM_PACKETS) {
fprintf(stderr, "Attempted to log a bad packet? \n");
return;
}
packet_log[type]++;
/*data_this_sec += handlers[type].size;*/
data_this_sec += act_size; /* HW */
ALL_BYTES += act_size; /* To get all bytes */
if (handlers[type].size == -1) { /* vari packet */
vari_sizes[type] += act_size;
}
this_sec = time(NULL);
if (this_sec != lasttime) {
lasttime = this_sec;
if (log_packets > 1) {
fprintf(stdout, "%d %d %d\n", this_sec - Start_Time, data_this_sec, outdata_this_sec);
}
if (Start_Time == 0) {
Start_Time = this_sec;
}
/* ignore baudage on the first few seconds of reception --
** that's when we get crushed by the motd being sent */
if (lasttime > Start_Time + 10) {
if (data_this_sec > Max_CPS)
Max_CPS = data_this_sec;
if (outdata_this_sec > Max_CPSout)
Max_CPSout = outdata_this_sec;
sumpl += data_this_sec;
s2 += (data_this_sec * data_this_sec);
sout2 += outdata_this_sec * outdata_this_sec;
sumout += outdata_this_sec;
numpl++;
}
data_this_sec = 0;
outdata_this_sec = 0;
}
}
int
Log_OPacket(tpe, size)
int tpe;
int size;
{
/* Log Packet will handle the per second resets of this */
if (log_packets == 0)
return;
outpacket_log[tpe]++;
outdata_this_sec += size;
#ifdef SHORT_PACKETS
if (tpe == CP_S_MESSAGE)
cp_msg_size += size; /* HW */
#endif
}
/* print out out the cool information on packet logging */
Dump_Packet_Log_Info()
{
int i;
time_t Now;
int total_bytes = 0;
int outtotal_bytes = 0;
int calc_temp;
Now = time(NULL);
printf("Packet Logging Summary:\n");
printf("Start time: %s ", ctime(&Start_Time));
printf(" End time: %s Elapsed play time: %3.2f min\n",
ctime(&Now), (float) ((Now - Start_Time) / 60));
printf("Maximum CPS in during normal play: %d bytes per sec\n", Max_CPS);
printf("Standard deviation in: %d\n",
(int) sqrt((numpl * s2 - sumpl * sumpl) / (numpl * (numpl - 1))));
printf("Maximum CPS out during normal play: %d bytes per sec\n", Max_CPSout);
printf("Standard deviation out: %d\n",
(int) sqrt((numpl * sout2 - sumout * sumout) / (numpl * (numpl - 1))));
#ifdef SHORT_PACKETS
/*total_bytes = ALL_BYTES;*//* Hope this works HW */
for (i = 0; i <= NUM_PACKETS; i++) { /* I think it must be <= */
if (handlers[i].size != -1)
total_bytes += handlers[i].size * packet_log[i];
else
total_bytes += vari_sizes[i];
} /* The result should be == ALL_BYTES HW */
#else
for (i = 0; i <= NUM_PACKETS; i++) {
total_bytes += handlers[i].size * packet_log[i];
}
#endif
for (i = 0; i <= NUM_SIZES; i++) {
#ifdef SHORT_PACKETS
if (handlers[i].size != -1)
outtotal_bytes += outpacket_log[i] * sizes[i];
else
outtotal_bytes += cp_msg_size; /* HW */
#else
outtotal_bytes += outpacket_log[i] * sizes[i];
#endif
}
printf("Total bytes received %d, average CPS: %4.1f\n",
total_bytes, (float) (total_bytes / (Now - Start_Time)));
printf("Server Packets Summary:\n");
printf("Num #Rcvd Size TotlBytes %Total\n");
for (i = 0; i <= NUM_PACKETS; i++) {
#ifdef SHORT_PACKETS
if (handlers[i].size != -1)
calc_temp = handlers[i].size * packet_log[i];
else
calc_temp = vari_sizes[i];
printf("%3d %5d %4d %9d %3.2f\n",
i, packet_log[i], handlers[i].size, calc_temp,
(float) (calc_temp * 100 / total_bytes));
#else
calc_temp = handlers[i].size * packet_log[i];
printf("%3d %5d %4d %9d %3.2f\n",
i, packet_log[i], handlers[i].size, calc_temp,
(float) (calc_temp * 100 / total_bytes));
#endif
}
printf("Total bytes sent %d, average CPS: %4.1f\n",
outtotal_bytes, (float) (outtotal_bytes / (Now - Start_Time)));
printf("Client Packets Summary:\n");
printf("Num #Sent Size TotlBytes %Total\n");
for (i = 0; i <= NUM_SIZES; i++) {
#ifdef SHORT_PACKETS
if (sizes[i] == -1)
calc_temp = cp_msg_size;
else
calc_temp = sizes[i] * outpacket_log[i];
printf("%3d %5d %4d %9d %3.2f\n",
i, outpacket_log[i], sizes[i], calc_temp,
(float) (calc_temp * 100 / outtotal_bytes));
}
#else
calc_temp = sizes[i] * outpacket_log[i];
printf("%3d %5d %4d %9d %3.2f\n",
i, outpacket_log[i], sizes[i], calc_temp,
(float) (calc_temp * 100 / outtotal_bytes));
}
#endif
}
#endif